summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--BUILD/FINISH.sh1
-rw-r--r--client/mysqlcheck.c21
-rw-r--r--client/mysqltest.cc2
-rw-r--r--cmake/bison.cmake4
-rw-r--r--extra/comp_err.c2
-rw-r--r--extra/mysqld_safe_helper.c2
-rw-r--r--include/m_string.h15
-rw-r--r--include/maria.h2
-rw-r--r--include/my_base.h11
-rw-r--r--include/my_handler_errors.h4
-rw-r--r--include/my_time.h2
-rw-r--r--include/myisam.h2
-rw-r--r--include/myisammrg.h3
-rw-r--r--include/mysql.h.pp2
-rw-r--r--include/mysql/plugin_audit.h.pp19
-rw-r--r--include/mysql/plugin_auth.h2
-rw-r--r--include/mysql/plugin_auth.h.pp21
-rw-r--r--include/mysql/plugin_encryption.h.pp19
-rw-r--r--include/mysql/plugin_ftparser.h.pp19
-rw-r--r--include/mysql/plugin_password_validation.h4
-rw-r--r--include/mysql/plugin_password_validation.h.pp23
-rw-r--r--include/mysql/service_my_snprintf.h15
-rw-r--r--include/mysql/service_thd_alloc.h17
-rw-r--r--include/mysql_com.h2
-rw-r--r--libmysqld/CMakeLists.txt4
-rw-r--r--libmysqld/lib_sql.cc12
-rw-r--r--mysql-test/extra/rpl_tests/rpl_charset.test28
-rw-r--r--mysql-test/include/gis_generic.inc2
-rwxr-xr-xmysql-test/mysql-test-run.pl4
-rw-r--r--mysql-test/r/analyze_format_json.result1
-rw-r--r--mysql-test/r/bug13633383.result66
-rw-r--r--mysql-test/r/case.result60
-rw-r--r--mysql-test/r/cast.result270
-rw-r--r--mysql-test/r/commit_1innodb.result1
-rw-r--r--mysql-test/r/compare.result2
-rw-r--r--mysql-test/r/create.result34
-rw-r--r--mysql-test/r/create_drop_binlog.result4
-rw-r--r--mysql-test/r/create_drop_trigger.result4
-rw-r--r--mysql-test/r/create_drop_view.result2
-rw-r--r--mysql-test/r/cte_nonrecursive.result2
-rw-r--r--mysql-test/r/cte_recursive.result17
-rw-r--r--mysql-test/r/ctype_binary.result18
-rw-r--r--mysql-test/r/ctype_cp1250_ch.result2
-rw-r--r--mysql-test/r/ctype_cp1251.result14
-rw-r--r--mysql-test/r/ctype_latin1.result22
-rw-r--r--mysql-test/r/ctype_latin2_ch.result2
-rw-r--r--mysql-test/r/ctype_tis620.result4
-rw-r--r--mysql-test/r/ctype_uca.result4
-rw-r--r--mysql-test/r/ctype_ucs.result18
-rw-r--r--mysql-test/r/ctype_utf8.result46
-rw-r--r--mysql-test/r/default.result15
-rw-r--r--mysql-test/r/delete_use_source.result151
-rw-r--r--mysql-test/r/derived.result2
-rw-r--r--mysql-test/r/derived_cond_pushdown.result18
-rw-r--r--mysql-test/r/derived_view.result50
-rw-r--r--mysql-test/r/distinct.result2
-rw-r--r--mysql-test/r/drop.result10
-rw-r--r--mysql-test/r/errors.result2
-rw-r--r--mysql-test/r/except.result527
-rw-r--r--mysql-test/r/explain.result16
-rw-r--r--mysql-test/r/explain_json.result2
-rw-r--r--mysql-test/r/flush-innodb.result2
-rw-r--r--mysql-test/r/flush.result10
-rw-r--r--mysql-test/r/func_compress.result2
-rw-r--r--mysql-test/r/func_debug.result1657
-rw-r--r--mysql-test/r/func_gconcat.result6
-rw-r--r--mysql-test/r/func_group.result41
-rw-r--r--mysql-test/r/func_hybrid_type.result506
-rw-r--r--mysql-test/r/func_in.result31
-rw-r--r--mysql-test/r/func_json.result26
-rw-r--r--mysql-test/r/func_math.result61
-rw-r--r--mysql-test/r/func_misc.result15
-rw-r--r--mysql-test/r/func_str.result242
-rw-r--r--mysql-test/r/func_time.result102
-rw-r--r--mysql-test/r/func_weight_string.result2
-rw-r--r--mysql-test/r/get_diagnostics.result6
-rw-r--r--mysql-test/r/gis-debug.result100
-rw-r--r--mysql-test/r/gis-precise.result3
-rw-r--r--mysql-test/r/gis-rtree.result218
-rw-r--r--mysql-test/r/gis.result2479
-rw-r--r--mysql-test/r/grant.result6
-rw-r--r--mysql-test/r/group_by.result4
-rw-r--r--mysql-test/r/having.result2
-rw-r--r--mysql-test/r/insert_notembedded.result2
-rw-r--r--mysql-test/r/intersect.result691
-rw-r--r--mysql-test/r/join.result2
-rw-r--r--mysql-test/r/join_outer.result4
-rw-r--r--mysql-test/r/join_outer_jcl6.result4
-rw-r--r--mysql-test/r/keywords.result29
-rw-r--r--mysql-test/r/last_value.result8
-rw-r--r--mysql-test/r/limit_rows_examined.result2
-rw-r--r--mysql-test/r/lowercase_view.result6
-rw-r--r--mysql-test/r/merge.result44
-rw-r--r--mysql-test/r/metadata.result504
-rw-r--r--mysql-test/r/myisam_explain_non_select_all.result12
-rw-r--r--mysql-test/r/myisam_mrr.result2
-rw-r--r--mysql-test/r/mysqld--help.result2
-rw-r--r--mysql-test/r/null.result400
-rw-r--r--mysql-test/r/olap.result54
-rw-r--r--mysql-test/r/parser.result9
-rw-r--r--mysql-test/r/partition.result2
-rw-r--r--mysql-test/r/partition_column.result2
-rw-r--r--mysql-test/r/partition_explicit_prune.result190
-rw-r--r--mysql-test/r/profiling.result2
-rw-r--r--mysql-test/r/ps.result8
-rw-r--r--mysql-test/r/ps_2myisam.result272
-rw-r--r--mysql-test/r/ps_3innodb.result272
-rw-r--r--mysql-test/r/ps_4heap.result272
-rw-r--r--mysql-test/r/ps_5merge.result544
-rw-r--r--mysql-test/r/range.result18
-rw-r--r--mysql-test/r/range_mrr_icp.result18
-rw-r--r--mysql-test/r/rename.result2
-rw-r--r--mysql-test/r/select.result4
-rw-r--r--mysql-test/r/select_jcl6.result4
-rw-r--r--mysql-test/r/select_pkeycache.result4
-rw-r--r--mysql-test/r/selectivity.result34
-rw-r--r--mysql-test/r/selectivity_innodb.result34
-rw-r--r--mysql-test/r/signal.result17
-rw-r--r--mysql-test/r/signal_code.result2
-rw-r--r--mysql-test/r/signal_demo3.result33
-rw-r--r--mysql-test/r/sp-anchor-row-type-cursor.result1003
-rw-r--r--mysql-test/r/sp-anchor-row-type-table.result681
-rw-r--r--mysql-test/r/sp-anchor-type.result967
-rw-r--r--mysql-test/r/sp-bugs.result11
-rw-r--r--mysql-test/r/sp-code.result6
-rw-r--r--mysql-test/r/sp-cursor.result482
-rw-r--r--mysql-test/r/sp-error.result4
-rw-r--r--mysql-test/r/sp-group.result2
-rw-r--r--mysql-test/r/sp-row.result2248
-rw-r--r--mysql-test/r/sp-security-anchor-type.result263
-rw-r--r--mysql-test/r/sp-vars.result58
-rw-r--r--mysql-test/r/sp.result133
-rw-r--r--mysql-test/r/status.result11
-rw-r--r--mysql-test/r/subselect.result97
-rw-r--r--mysql-test/r/subselect2.result4
-rw-r--r--mysql-test/r/subselect3.result28
-rw-r--r--mysql-test/r/subselect3_jcl6.result28
-rw-r--r--mysql-test/r/subselect4.result8
-rw-r--r--mysql-test/r/subselect_cache.result4
-rw-r--r--mysql-test/r/subselect_exists2in.result34
-rw-r--r--mysql-test/r/subselect_extra_no_semijoin.result12
-rw-r--r--mysql-test/r/subselect_mat.result126
-rw-r--r--mysql-test/r/subselect_mat_cost_bugs.result6
-rw-r--r--mysql-test/r/subselect_no_exists_to_in.result103
-rw-r--r--mysql-test/r/subselect_no_mat.result97
-rw-r--r--mysql-test/r/subselect_no_opts.result119
-rw-r--r--mysql-test/r/subselect_no_scache.result97
-rw-r--r--mysql-test/r/subselect_no_semijoin.result119
-rw-r--r--mysql-test/r/subselect_partial_match.result2
-rw-r--r--mysql-test/r/subselect_sj.result12
-rw-r--r--mysql-test/r/subselect_sj2_mat.result2
-rw-r--r--mysql-test/r/subselect_sj_jcl6.result12
-rw-r--r--mysql-test/r/subselect_sj_mat.result72
-rw-r--r--mysql-test/r/table_elim.result14
-rw-r--r--mysql-test/r/temp_table.result16
-rw-r--r--mysql-test/r/trigger.result29
-rw-r--r--mysql-test/r/type_date.result53
-rw-r--r--mysql-test/r/type_datetime.result33
-rw-r--r--mysql-test/r/type_datetime_hires.result12
-rw-r--r--mysql-test/r/type_decimal.result49
-rw-r--r--mysql-test/r/type_enum.result94
-rw-r--r--mysql-test/r/type_float.result14
-rw-r--r--mysql-test/r/type_newdecimal.result6
-rw-r--r--mysql-test/r/type_ranges.result2
-rw-r--r--mysql-test/r/type_set.result36
-rw-r--r--mysql-test/r/type_time.result78
-rw-r--r--mysql-test/r/type_time_hires.result12
-rw-r--r--mysql-test/r/type_timestamp.result76
-rw-r--r--mysql-test/r/type_timestamp_hires.result12
-rw-r--r--mysql-test/r/udf.result16
-rw-r--r--mysql-test/r/udf_notembedded.result6
-rw-r--r--mysql-test/r/union.result278
-rw-r--r--mysql-test/r/user_var.result19
-rw-r--r--mysql-test/r/userstat.result1
-rw-r--r--mysql-test/r/variables.result4
-rw-r--r--mysql-test/r/view.result107
-rw-r--r--mysql-test/r/warnings.result1
-rw-r--r--mysql-test/r/win.result12
-rw-r--r--mysql-test/r/win_first_last_value.result14
-rw-r--r--mysql-test/r/win_insert_select.result4
-rw-r--r--mysql-test/suite/archive/archive_gis.result4
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_sp.result86
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result227
-rw-r--r--mysql-test/suite/binlog/r/binlog_unsafe.result35
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_sp.test41
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test108
-rw-r--r--mysql-test/suite/compat/oracle/r/binlog_stm_ps.result67
-rw-r--r--mysql-test/suite/compat/oracle/r/binlog_stm_sp.result477
-rw-r--r--mysql-test/suite/compat/oracle/r/exception.result409
-rw-r--r--mysql-test/suite/compat/oracle/r/func_case.result7
-rw-r--r--mysql-test/suite/compat/oracle/r/func_concat.result257
-rw-r--r--mysql-test/suite/compat/oracle/r/func_decode.result33
-rw-r--r--mysql-test/suite/compat/oracle/r/func_length.result21
-rw-r--r--mysql-test/suite/compat/oracle/r/func_misc.result319
-rw-r--r--mysql-test/suite/compat/oracle/r/misc.result12
-rw-r--r--mysql-test/suite/compat/oracle/r/ps.result249
-rw-r--r--mysql-test/suite/compat/oracle/r/sequence.result77
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-anonymous.result220
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-code.result1483
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-cursor-decl.result290
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result1332
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-cursor.result951
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-goto.result834
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-param.result132
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-row.result3072
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-security.result288
-rw-r--r--mysql-test/suite/compat/oracle/r/sp.result2284
-rw-r--r--mysql-test/suite/compat/oracle/r/trigger.result100
-rw-r--r--mysql-test/suite/compat/oracle/r/truncate.result10
-rw-r--r--mysql-test/suite/compat/oracle/r/type_blob.result8
-rw-r--r--mysql-test/suite/compat/oracle/r/type_clob.result15
-rw-r--r--mysql-test/suite/compat/oracle/r/type_date.result8
-rw-r--r--mysql-test/suite/compat/oracle/r/type_number.result15
-rw-r--r--mysql-test/suite/compat/oracle/r/type_raw.result15
-rw-r--r--mysql-test/suite/compat/oracle/r/type_varchar.result9
-rw-r--r--mysql-test/suite/compat/oracle/r/type_varchar2.result23
-rw-r--r--mysql-test/suite/compat/oracle/r/variables.result39
-rw-r--r--mysql-test/suite/compat/oracle/t/binlog_stm_ps.test37
-rw-r--r--mysql-test/suite/compat/oracle/t/binlog_stm_sp.test196
-rw-r--r--mysql-test/suite/compat/oracle/t/exception.test457
-rw-r--r--mysql-test/suite/compat/oracle/t/func_case.test9
-rw-r--r--mysql-test/suite/compat/oracle/t/func_concat.test116
-rw-r--r--mysql-test/suite/compat/oracle/t/func_decode.test21
-rw-r--r--mysql-test/suite/compat/oracle/t/func_length.test18
-rw-r--r--mysql-test/suite/compat/oracle/t/func_misc.test346
-rw-r--r--mysql-test/suite/compat/oracle/t/misc.test10
-rw-r--r--mysql-test/suite/compat/oracle/t/ps.test266
-rw-r--r--mysql-test/suite/compat/oracle/t/sequence.test43
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-anonymous.test244
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-code.test1057
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-cursor-decl.test295
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test1424
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-cursor.test954
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-goto.test872
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-param.inc9
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-param.test37
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc6
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-row.test2377
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-security.test345
-rw-r--r--mysql-test/suite/compat/oracle/t/sp.test2133
-rw-r--r--mysql-test/suite/compat/oracle/t/trigger.test106
-rw-r--r--mysql-test/suite/compat/oracle/t/truncate.test16
-rw-r--r--mysql-test/suite/compat/oracle/t/type_blob.test4
-rw-r--r--mysql-test/suite/compat/oracle/t/type_clob.test10
-rw-r--r--mysql-test/suite/compat/oracle/t/type_date.test4
-rw-r--r--mysql-test/suite/compat/oracle/t/type_number.test9
-rw-r--r--mysql-test/suite/compat/oracle/t/type_raw.test10
-rw-r--r--mysql-test/suite/compat/oracle/t/type_varchar.test9
-rw-r--r--mysql-test/suite/compat/oracle/t/type_varchar2.test19
-rw-r--r--mysql-test/suite/compat/oracle/t/variables.test38
-rw-r--r--mysql-test/suite/engines/iuds/r/insert_number.result16
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_func_view.result8
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_trig_0102.result4
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_trig_0407.result4
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_views.result32
-rw-r--r--mysql-test/suite/funcs_1/r/memory_func_view.result8
-rw-r--r--mysql-test/suite/funcs_1/r/memory_trig_0102.result4
-rw-r--r--mysql-test/suite/funcs_1/r/memory_trig_0407.result4
-rw-r--r--mysql-test/suite/funcs_1/r/memory_views.result32
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_func_view.result8
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_trig_0102.result4
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_trig_0407.result4
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_views-big.result32
-rw-r--r--mysql-test/suite/funcs_1/views/views_master.inc4
-rw-r--r--mysql-test/suite/gcol/r/gcol_supported_sql_funcs_innodb.result6
-rw-r--r--mysql-test/suite/gcol/r/gcol_supported_sql_funcs_myisam.result6
-rw-r--r--mysql-test/suite/innodb/r/innodb_gis.result4
-rw-r--r--mysql-test/suite/innodb/r/table_flags.result17
-rw-r--r--mysql-test/suite/innodb/t/table_flags.test17
-rw-r--r--mysql-test/suite/innodb_fts/r/fulltext_misc.result6
-rw-r--r--mysql-test/suite/innodb_gis/r/0.result4
-rw-r--r--mysql-test/suite/innodb_gis/r/1.result25
-rw-r--r--mysql-test/suite/innodb_gis/r/alter_spatial_index.result3
-rw-r--r--mysql-test/suite/innodb_gis/r/create_spatial_index.result4
-rw-r--r--mysql-test/suite/innodb_gis/r/gis.result25
-rw-r--r--mysql-test/suite/innodb_gis/r/precise.result3
-rw-r--r--mysql-test/suite/innodb_gis/t/1.test12
-rw-r--r--mysql-test/suite/innodb_gis/t/alter_spatial_index.test4
-rw-r--r--mysql-test/suite/innodb_gis/t/create_spatial_index.test2
-rw-r--r--mysql-test/suite/innodb_gis/t/gis.test11
-rw-r--r--mysql-test/suite/innodb_gis/t/precise.test2
-rw-r--r--mysql-test/suite/maria/ps_maria.result272
-rw-r--r--mysql-test/suite/perfschema/r/dml_setup_instruments.result2
-rw-r--r--mysql-test/suite/perfschema/r/view_table_io.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_charset.result23
-rw-r--r--mysql-test/suite/rpl/r/rpl_create_drop_trigger.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_create_drop_view.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_drop_view.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_slave_grp_exec.result1
-rw-r--r--mysql-test/suite/rpl/r/rpl_sp.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_stm_sp.result26
-rw-r--r--mysql-test/suite/rpl/r/rpl_trans_no_trans.result44
-rw-r--r--mysql-test/suite/rpl/r/sequence.result129
-rw-r--r--mysql-test/suite/rpl/t/rpl_create_drop_view.test2
-rw-r--r--mysql-test/suite/rpl/t/rpl_drop_view.test4
-rw-r--r--mysql-test/suite/rpl/t/rpl_slave_grp_exec.test1
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_sp.test30
-rw-r--r--mysql-test/suite/rpl/t/rpl_trans_no_trans.test72
-rw-r--r--mysql-test/suite/rpl/t/sequence.cnf8
-rw-r--r--mysql-test/suite/rpl/t/sequence.test52
-rw-r--r--mysql-test/suite/sql_sequence/alter.result240
-rw-r--r--mysql-test/suite/sql_sequence/alter.test141
-rw-r--r--mysql-test/suite/sql_sequence/aria.result66
-rw-r--r--mysql-test/suite/sql_sequence/aria.test43
-rw-r--r--mysql-test/suite/sql_sequence/binlog.result33
-rw-r--r--mysql-test/suite/sql_sequence/binlog.test27
-rw-r--r--mysql-test/suite/sql_sequence/create.result500
-rw-r--r--mysql-test/suite/sql_sequence/create.test377
-rw-r--r--mysql-test/suite/sql_sequence/disabled.def0
-rw-r--r--mysql-test/suite/sql_sequence/gtid-master.opt3
-rw-r--r--mysql-test/suite/sql_sequence/gtid-slave.opt4
-rw-r--r--mysql-test/suite/sql_sequence/gtid.result829
-rw-r--r--mysql-test/suite/sql_sequence/gtid.test704
-rw-r--r--mysql-test/suite/sql_sequence/mysqldump.result41
-rw-r--r--mysql-test/suite/sql_sequence/mysqldump.test15
-rw-r--r--mysql-test/suite/sql_sequence/next.result514
-rw-r--r--mysql-test/suite/sql_sequence/next.test262
-rw-r--r--mysql-test/suite/sql_sequence/other.result164
-rw-r--r--mysql-test/suite/sql_sequence/other.test133
-rw-r--r--mysql-test/suite/sql_sequence/read_only.result38
-rw-r--r--mysql-test/suite/sql_sequence/read_only.test44
-rw-r--r--mysql-test/suite/sql_sequence/replication-master.opt1
-rw-r--r--mysql-test/suite/sql_sequence/replication-slave.opt1
-rw-r--r--mysql-test/suite/sql_sequence/replication.result1067
-rw-r--r--mysql-test/suite/sql_sequence/replication.test861
-rw-r--r--mysql-test/suite/sql_sequence/setval.result256
-rw-r--r--mysql-test/suite/sql_sequence/setval.test139
-rw-r--r--mysql-test/suite/sql_sequence/temporary.result12
-rw-r--r--mysql-test/suite/sql_sequence/temporary.test16
-rw-r--r--mysql-test/suite/sql_sequence/view.result26
-rw-r--r--mysql-test/suite/sql_sequence/view.test29
-rw-r--r--mysql-test/suite/storage_engine/create_table.result2
-rw-r--r--mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/big_tables_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/binlog_cache_size_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/binlog_stmt_cache_size_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/character_set_client_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/character_set_connection_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/character_set_database_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/character_set_filesystem_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/character_set_results_basic.resultbin16480 -> 16253 bytes
-rw-r--r--mysql-test/suite/sys_vars/r/character_set_server_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/collation_connection_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/collation_database_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/collation_server_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/completion_type_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/concurrent_insert_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/connect_timeout_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/default_master_connection_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/default_week_format_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/delayed_insert_limit_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/delayed_insert_timeout_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/delayed_queue_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/div_precision_increment_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/event_scheduler_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/expire_logs_days_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/flush_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/general_log_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/identity_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/insert_id_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/key_buffer_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/key_cache_age_threshold_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/key_cache_block_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/key_cache_division_limit_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/key_cache_file_hash_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/lc_time_names_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/local_infile_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_binlog_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_binlog_stmt_cache_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_connect_errors_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_connections_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_prepared_stmt_count_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/myisam_stats_method_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/mysql56_temporal_format_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/old_mode_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/query_cache_limit_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/query_cache_size_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/read_only_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/relay_log_purge_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/slow_launch_time_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/slow_query_log_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sql_mode_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sync_binlog_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sync_frm_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_embedded.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result4
-rw-r--r--mysql-test/suite/sys_vars/r/table_definition_cache_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/table_open_cache_basic.result2
-rw-r--r--mysql-test/suite/sys_vars/r/tx_isolation_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/big_tables_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/binlog_cache_size_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/binlog_stmt_cache_size_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/bulk_insert_buffer_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/character_set_client_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/character_set_connection_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/character_set_database_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/character_set_filesystem_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/character_set_results_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/character_set_server_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/collation_connection_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/collation_database_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/collation_server_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/completion_type_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/concurrent_insert_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/connect_timeout_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/default_master_connection_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/default_week_format_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/delayed_insert_limit_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/delayed_insert_timeout_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/delayed_queue_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/div_precision_increment_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/event_scheduler_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/expire_logs_days_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/flush_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/general_log_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/identity_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/insert_id_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/key_buffer_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/key_cache_age_threshold_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/key_cache_block_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/key_cache_division_limit_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/key_cache_file_hash_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/lc_time_names_basic.test3
-rw-r--r--mysql-test/suite/sys_vars/t/local_infile_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/max_binlog_cache_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/max_binlog_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/max_binlog_stmt_cache_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/max_connect_errors_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/max_connections_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/max_prepared_stmt_count_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/myisam_stats_method_basic.test5
-rw-r--r--mysql-test/suite/sys_vars/t/mysql56_temporal_format_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/old_mode_basic.test5
-rw-r--r--mysql-test/suite/sys_vars/t/query_cache_limit_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/query_cache_min_res_unit_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/query_cache_size_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/read_only_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/relay_log_purge_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/slow_launch_time_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/slow_query_log_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/sql_mode_basic.test5
-rw-r--r--mysql-test/suite/sys_vars/t/sync_binlog_basic.test4
-rw-r--r--mysql-test/suite/sys_vars/t/sync_frm_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/table_definition_cache_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/table_open_cache_basic.test2
-rw-r--r--mysql-test/suite/sys_vars/t/tx_isolation_basic.test4
-rw-r--r--mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result6
-rw-r--r--mysql-test/suite/vcol/r/vcol_view_innodb.result2
-rw-r--r--mysql-test/suite/vcol/r/vcol_view_myisam.result2
-rw-r--r--mysql-test/t/bug13633383.test1
-rw-r--r--mysql-test/t/case.test55
-rw-r--r--mysql-test/t/cast.test73
-rw-r--r--mysql-test/t/create.test16
-rw-r--r--mysql-test/t/ctype_utf8.test29
-rw-r--r--mysql-test/t/default.test2
-rw-r--r--mysql-test/t/delete_use_source.test132
-rw-r--r--mysql-test/t/drop.test2
-rw-r--r--mysql-test/t/except.test83
-rw-r--r--mysql-test/t/func_debug.test477
-rw-r--r--mysql-test/t/func_gconcat.test2
-rw-r--r--mysql-test/t/func_group.test27
-rw-r--r--mysql-test/t/func_hybrid_type.test156
-rw-r--r--mysql-test/t/func_in.test26
-rw-r--r--mysql-test/t/func_json.test23
-rw-r--r--mysql-test/t/func_math.test51
-rw-r--r--mysql-test/t/func_misc.test16
-rw-r--r--mysql-test/t/func_str.test90
-rw-r--r--mysql-test/t/func_time.test63
-rw-r--r--mysql-test/t/get_diagnostics.test1
-rw-r--r--mysql-test/t/gis-debug.test91
-rw-r--r--mysql-test/t/gis-precise.test1
-rw-r--r--mysql-test/t/gis-rtree.test8
-rw-r--r--mysql-test/t/gis.test955
-rw-r--r--mysql-test/t/intersect.test192
-rw-r--r--mysql-test/t/keywords.test41
-rw-r--r--mysql-test/t/lowercase_view.test6
-rw-r--r--mysql-test/t/merge.test33
-rw-r--r--mysql-test/t/metadata.test276
-rw-r--r--mysql-test/t/null.test135
-rw-r--r--mysql-test/t/olap.test43
-rw-r--r--mysql-test/t/parser.test12
-rw-r--r--mysql-test/t/partition.test1
-rw-r--r--mysql-test/t/select.test1
-rw-r--r--mysql-test/t/sp-anchor-row-type-cursor.test1095
-rw-r--r--mysql-test/t/sp-anchor-row-type-table.test761
-rw-r--r--mysql-test/t/sp-anchor-type.test677
-rw-r--r--mysql-test/t/sp-bugs.test14
-rw-r--r--mysql-test/t/sp-cursor.test476
-rw-r--r--mysql-test/t/sp-row-vs-var.inc6
-rw-r--r--mysql-test/t/sp-row.test1473
-rw-r--r--mysql-test/t/sp-security-anchor-type.test328
-rw-r--r--mysql-test/t/sp-vars.test49
-rw-r--r--mysql-test/t/sp.test116
-rw-r--r--mysql-test/t/subselect.test8
-rw-r--r--mysql-test/t/trigger.test25
-rw-r--r--mysql-test/t/truncate.test2
-rw-r--r--mysql-test/t/type_date.test25
-rw-r--r--mysql-test/t/type_datetime.test21
-rw-r--r--mysql-test/t/type_decimal.test43
-rw-r--r--mysql-test/t/type_enum.test66
-rw-r--r--mysql-test/t/type_set.test22
-rw-r--r--mysql-test/t/type_time.test16
-rw-r--r--mysql-test/t/type_timestamp.test51
-rw-r--r--mysql-test/t/udf.test16
-rw-r--r--mysql-test/t/udf_notembedded.test6
-rw-r--r--mysql-test/t/union.test169
-rw-r--r--mysql-test/t/user_var.test15
-rw-r--r--mysql-test/t/variables.test4
-rw-r--r--mysql-test/t/view.test40
-rw-r--r--mysql-test/t/win.test13
-rw-r--r--mysql-test/t/win_first_last_value.test10
-rw-r--r--mysql-test/t/win_insert_select.test2
-rw-r--r--mysql-test/valgrind.supp1
-rw-r--r--mysys/safemalloc.c8
-rw-r--r--mysys/thr_lock.c3
-rw-r--r--plugin/auth_examples/qa_auth_interface.c4
-rw-r--r--plugin/feedback/feedback.cc4
-rw-r--r--plugin/handler_socket/handlersocket/database.cpp6
-rw-r--r--plugin/qc_info/qc_info.cc2
-rw-r--r--plugin/simple_password_check/simple_password_check.c3
-rwxr-xr-x[-rw-r--r--]scripts/wsrep_sst_common.sh0
-rw-r--r--sql/CMakeLists.txt14
-rw-r--r--sql/create_options.cc15
-rw-r--r--sql/create_options.h18
-rw-r--r--sql/datadict.cc46
-rw-r--r--sql/datadict.h19
-rw-r--r--sql/event_data_objects.cc61
-rw-r--r--sql/event_data_objects.h35
-rw-r--r--sql/event_db_repository.cc59
-rw-r--r--sql/event_db_repository.h20
-rw-r--r--sql/event_parse_data.cc14
-rw-r--r--sql/event_parse_data.h8
-rw-r--r--sql/event_queue.cc28
-rw-r--r--sql/event_queue.h14
-rw-r--r--sql/event_scheduler.cc2
-rw-r--r--sql/events.cc63
-rw-r--r--sql/events.h15
-rw-r--r--sql/field.cc1217
-rw-r--r--sql/field.h772
-rw-r--r--sql/field_conv.cc2
-rw-r--r--sql/filesort.cc12
-rw-r--r--sql/ha_partition.cc33
-rw-r--r--sql/ha_partition.h6
-rw-r--r--sql/ha_sequence.cc438
-rw-r--r--sql/ha_sequence.h165
-rw-r--r--sql/handler.cc125
-rw-r--r--sql/handler.h131
-rw-r--r--sql/item.cc1807
-rw-r--r--sql/item.h1431
-rw-r--r--sql/item_cmpfunc.cc1533
-rw-r--r--sql/item_cmpfunc.h839
-rw-r--r--sql/item_create.cc710
-rw-r--r--sql/item_create.h29
-rw-r--r--sql/item_func.cc1873
-rw-r--r--sql/item_func.h866
-rw-r--r--sql/item_geofunc.cc13
-rw-r--r--sql/item_geofunc.h363
-rw-r--r--sql/item_inetfunc.h4
-rw-r--r--sql/item_jsonfunc.cc9
-rw-r--r--sql/item_jsonfunc.h29
-rw-r--r--sql/item_row.h10
-rw-r--r--sql/item_strfunc.cc503
-rw-r--r--sql/item_strfunc.h157
-rw-r--r--sql/item_subselect.cc111
-rw-r--r--sql/item_subselect.h33
-rw-r--r--sql/item_sum.cc308
-rw-r--r--sql/item_sum.h84
-rw-r--r--sql/item_timefunc.cc175
-rw-r--r--sql/item_timefunc.h231
-rw-r--r--sql/item_windowfunc.cc14
-rw-r--r--sql/item_windowfunc.h49
-rw-r--r--sql/item_xmlfunc.cc16
-rw-r--r--sql/key.cc2
-rw-r--r--sql/key.h4
-rw-r--r--sql/keycaches.cc8
-rw-r--r--sql/keycaches.h4
-rw-r--r--sql/lex.h31
-rw-r--r--sql/lock.cc15
-rw-r--r--sql/lock.h3
-rw-r--r--sql/log.cc120
-rw-r--r--sql/log.h6
-rw-r--r--sql/log_event.cc92
-rw-r--r--sql/log_event.h57
-rw-r--r--sql/mdl.cc7
-rw-r--r--sql/mysqld.cc43
-rw-r--r--sql/mysqld.h13
-rw-r--r--sql/opt_range.cc112
-rw-r--r--sql/opt_range.h11
-rw-r--r--sql/opt_subselect.cc50
-rw-r--r--sql/opt_table_elimination.cc4
-rw-r--r--sql/parse_file.cc15
-rw-r--r--sql/parse_file.h17
-rw-r--r--sql/partition_element.h16
-rw-r--r--sql/partition_info.cc25
-rw-r--r--sql/partition_info.h6
-rw-r--r--sql/procedure.cc2
-rw-r--r--sql/procedure.h17
-rw-r--r--sql/protocol.cc30
-rw-r--r--sql/rpl_gtid.cc28
-rw-r--r--sql/rpl_gtid.h12
-rw-r--r--sql/rpl_mi.cc37
-rw-r--r--sql/rpl_mi.h18
-rw-r--r--sql/rpl_parallel.h38
-rw-r--r--sql/rpl_record.cc18
-rw-r--r--sql/rpl_record_old.cc4
-rw-r--r--sql/rpl_utility.cc12
-rw-r--r--sql/session_tracker.cc12
-rw-r--r--sql/set_var.cc33
-rw-r--r--sql/set_var.h28
-rw-r--r--sql/share/errmsg-utf8.txt45
-rw-r--r--sql/slave.cc5
-rw-r--r--sql/slave.h2
-rw-r--r--sql/sp.cc192
-rw-r--r--sql/sp.h38
-rw-r--r--sql/sp_cache.cc8
-rw-r--r--sql/sp_cache.h4
-rw-r--r--sql/sp_head.cc1123
-rw-r--r--sql/sp_head.h578
-rw-r--r--sql/sp_pcontext.cc406
-rw-r--r--sql/sp_pcontext.h333
-rw-r--r--sql/sp_rcontext.cc432
-rw-r--r--sql/sp_rcontext.h64
-rw-r--r--sql/sql_acl.cc246
-rw-r--r--sql/sql_acl.h21
-rw-r--r--sql/sql_admin.cc23
-rw-r--r--sql/sql_admin.h2
-rw-r--r--sql/sql_alter.cc20
-rw-r--r--sql/sql_alter.h192
-rw-r--r--sql/sql_analyse.cc2
-rw-r--r--sql/sql_base.cc198
-rw-r--r--sql/sql_base.h6
-rw-r--r--sql/sql_builtin.cc.in8
-rw-r--r--sql/sql_cache.cc2
-rw-r--r--sql/sql_cache.h4
-rw-r--r--sql/sql_class.cc204
-rw-r--r--sql/sql_class.h439
-rw-r--r--sql/sql_cmd.h3
-rw-r--r--sql/sql_connect.cc4
-rw-r--r--sql/sql_connect.h1
-rw-r--r--sql/sql_const.h1
-rw-r--r--sql/sql_cte.cc9
-rw-r--r--sql/sql_cte.h12
-rw-r--r--sql/sql_cursor.cc10
-rw-r--r--sql/sql_cursor.h5
-rw-r--r--sql/sql_db.cc104
-rw-r--r--sql/sql_db.h13
-rw-r--r--sql/sql_delete.cc104
-rw-r--r--sql/sql_delete.h3
-rw-r--r--sql/sql_derived.cc19
-rw-r--r--sql/sql_digest.cc2
-rw-r--r--sql/sql_error.cc153
-rw-r--r--sql/sql_error.h551
-rw-r--r--sql/sql_explain.cc56
-rw-r--r--sql/sql_explain.h9
-rw-r--r--sql/sql_handler.cc9
-rw-r--r--sql/sql_handler.h5
-rw-r--r--sql/sql_help.cc10
-rw-r--r--sql/sql_insert.cc8
-rw-r--r--sql/sql_lex.cc2319
-rw-r--r--sql/sql_lex.h806
-rw-r--r--sql/sql_list.h16
-rw-r--r--sql/sql_load.cc28
-rw-r--r--sql/sql_parse.cc661
-rw-r--r--sql/sql_parse.h25
-rw-r--r--sql/sql_partition.cc44
-rw-r--r--sql/sql_partition.h4
-rw-r--r--sql/sql_partition_admin.cc28
-rw-r--r--sql/sql_plugin.cc82
-rw-r--r--sql/sql_plugin.h18
-rw-r--r--sql/sql_plugin_compat.h2
-rw-r--r--sql/sql_prepare.cc58
-rw-r--r--sql/sql_profile.cc4
-rw-r--r--sql/sql_reload.cc2
-rw-r--r--sql/sql_rename.cc19
-rw-r--r--sql/sql_repl.cc9
-rw-r--r--sql/sql_select.cc292
-rw-r--r--sql/sql_select.h10
-rw-r--r--sql/sql_sequence.cc931
-rw-r--r--sql/sql_sequence.h168
-rw-r--r--sql/sql_servers.cc4
-rw-r--r--sql/sql_show.cc805
-rw-r--r--sql/sql_show.h12
-rw-r--r--sql/sql_signal.cc90
-rw-r--r--sql/sql_signal.h21
-rw-r--r--sql/sql_statistics.cc41
-rw-r--r--sql/sql_statistics.h14
-rw-r--r--sql/sql_string.cc61
-rw-r--r--sql/sql_string.h8
-rw-r--r--sql/sql_table.cc1035
-rw-r--r--sql/sql_table.h14
-rw-r--r--sql/sql_test.cc13
-rw-r--r--sql/sql_time.cc42
-rw-r--r--sql/sql_time.h2
-rw-r--r--sql/sql_trigger.cc166
-rw-r--r--sql/sql_trigger.h45
-rw-r--r--sql/sql_truncate.cc21
-rw-r--r--sql/sql_type.cc4878
-rw-r--r--sql/sql_type.h2519
-rw-r--r--sql/sql_udf.cc28
-rw-r--r--sql/sql_udf.h8
-rw-r--r--sql/sql_union.cc692
-rw-r--r--sql/sql_update.cc7
-rw-r--r--sql/sql_view.cc130
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/sql_window.cc10
-rw-r--r--sql/sql_window.h19
-rw-r--r--sql/sql_yacc.yy3193
-rw-r--r--sql/sql_yacc_ora.yy17113
-rw-r--r--sql/strfunc.cc16
-rw-r--r--sql/strfunc.h9
-rw-r--r--sql/structs.h139
-rw-r--r--sql/sys_vars.cc28
-rw-r--r--sql/sys_vars.ic110
-rw-r--r--sql/table.cc201
-rw-r--r--sql/table.h118
-rw-r--r--sql/temporary_tables.cc10
-rw-r--r--sql/transaction.cc8
-rw-r--r--sql/transaction.h6
-rw-r--r--sql/udf_example.c22
-rw-r--r--sql/udf_example.def6
-rw-r--r--sql/unireg.cc30
-rw-r--r--sql/wsrep_binlog.cc4
-rw-r--r--sql/wsrep_hton.cc3
-rw-r--r--sql/wsrep_mysqld.cc37
-rw-r--r--sql/wsrep_mysqld.h2
-rw-r--r--sql/wsrep_thd.cc3
-rw-r--r--sql/wsrep_var.cc4
-rw-r--r--storage/archive/azio.c2
-rw-r--r--storage/archive/azlib.h3
-rw-r--r--storage/blackhole/ha_blackhole.cc2
-rw-r--r--storage/blackhole/ha_blackhole.h2
-rw-r--r--storage/cassandra/ha_cassandra.cc40
-rw-r--r--storage/connect/ha_connect.cc82
-rw-r--r--storage/connect/ha_connect.h8
-rw-r--r--storage/connect/jsonudf.cpp9
-rw-r--r--storage/connect/tabext.cpp2
-rw-r--r--storage/connect/tabtbl.cpp2
-rw-r--r--storage/connect/tabutil.cpp4
-rw-r--r--storage/csv/ha_tina.cc4
-rw-r--r--storage/csv/ha_tina.h4
-rw-r--r--storage/example/ha_example.cc6
-rw-r--r--storage/example/ha_example.h2
-rw-r--r--storage/federated/ha_federated.cc50
-rw-r--r--storage/federated/ha_federated.h2
-rw-r--r--storage/federatedx/ha_federatedx.cc34
-rw-r--r--storage/federatedx/ha_federatedx.h2
-rw-r--r--storage/heap/ha_heap.cc50
-rw-r--r--storage/heap/ha_heap.h3
-rw-r--r--storage/heap/hp_block.c4
-rw-r--r--storage/innobase/buf/buf0flu.cc2
-rw-r--r--storage/innobase/dict/dict0dict.cc1
-rw-r--r--storage/innobase/dict/dict0load.cc11
-rw-r--r--storage/innobase/handler/ha_innodb.cc109
-rw-r--r--storage/innobase/handler/ha_innodb.h4
-rw-r--r--storage/innobase/handler/handler0alter.cc66
-rw-r--r--storage/innobase/include/btr0cur.h5
-rw-r--r--storage/innobase/include/dict0dict.ic3
-rw-r--r--storage/innobase/include/dict0mem.h34
-rw-r--r--storage/innobase/include/ut0dbg.h2
-rw-r--r--storage/innobase/include/ut0stage.h2
-rw-r--r--storage/innobase/que/que0que.cc1
-rw-r--r--storage/innobase/row/row0ins.cc26
-rw-r--r--storage/innobase/row/row0mysql.cc6
-rw-r--r--storage/innobase/row/row0sel.cc26
-rw-r--r--storage/innobase/row/row0upd.cc30
-rw-r--r--storage/maria/ha_maria.cc50
-rw-r--r--storage/maria/ha_maria.h6
-rw-r--r--storage/maria/ma_create.c2
-rw-r--r--storage/maria/ma_ft_update.c2
-rw-r--r--storage/maria/ma_unique.c6
-rw-r--r--storage/maria/ma_update.c3
-rw-r--r--storage/maria/maria_def.h2
-rw-r--r--storage/mroonga/ha_mroonga.cpp152
-rw-r--r--storage/mroonga/ha_mroonga.hpp29
-rw-r--r--storage/mroonga/lib/mrn_condition_converter.cpp4
-rw-r--r--storage/mroonga/mrn_table.cpp6
-rw-r--r--storage/myisam/ft_update.c2
-rw-r--r--storage/myisam/ha_myisam.cc9
-rw-r--r--storage/myisam/ha_myisam.h4
-rw-r--r--storage/myisam/mi_create.c2
-rw-r--r--storage/myisam/mi_unique.c5
-rw-r--r--storage/myisam/mi_update.c3
-rw-r--r--storage/myisam/myisamdef.h2
-rw-r--r--storage/myisammrg/ha_myisammrg.cc6
-rw-r--r--storage/myisammrg/ha_myisammrg.h2
-rw-r--r--storage/myisammrg/myrg_update.c3
-rw-r--r--storage/myisammrg/mysql-test/storage_engine/create_table.rdiff4
-rw-r--r--storage/oqgraph/ha_oqgraph.cc23
-rw-r--r--storage/oqgraph/ha_oqgraph.h4
-rw-r--r--storage/perfschema/ha_perfschema.cc2
-rw-r--r--storage/perfschema/ha_perfschema.h5
-rw-r--r--storage/perfschema/pfs.cc2
-rw-r--r--storage/perfschema/pfs_column_values.cc36
-rw-r--r--storage/perfschema/pfs_column_values.h18
-rw-r--r--storage/perfschema/pfs_engine_table.cc8
-rw-r--r--storage/perfschema/pfs_engine_table.h6
-rw-r--r--storage/perfschema/table_setup_actors.cc2
-rw-r--r--storage/perfschema/table_setup_actors.h2
-rw-r--r--storage/perfschema/table_setup_consumers.cc2
-rw-r--r--storage/perfschema/table_setup_consumers.h2
-rw-r--r--storage/perfschema/table_setup_instruments.cc2
-rw-r--r--storage/perfschema/table_setup_instruments.h2
-rw-r--r--storage/perfschema/table_setup_objects.cc2
-rw-r--r--storage/perfschema/table_setup_objects.h2
-rw-r--r--storage/perfschema/table_setup_timers.cc2
-rw-r--r--storage/perfschema/table_setup_timers.h2
-rw-r--r--storage/perfschema/table_threads.cc2
-rw-r--r--storage/perfschema/table_threads.h2
-rw-r--r--storage/rocksdb/ha_rocksdb.cc9
-rw-r--r--storage/rocksdb/ha_rocksdb.h4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result4
-rw-r--r--storage/rocksdb/rdb_datadic.cc10
-rw-r--r--storage/sequence/sequence.cc4
-rw-r--r--storage/sphinx/ha_sphinx.cc18
-rw-r--r--storage/sphinx/ha_sphinx.h2
-rw-r--r--storage/spider/ha_spider.cc9
-rw-r--r--storage/spider/ha_spider.h6
-rw-r--r--storage/spider/spd_db_conn.cc39
-rw-r--r--storage/spider/spd_db_handlersocket.cc2
-rw-r--r--storage/spider/spd_db_mysql.cc12
-rw-r--r--storage/spider/spd_db_oracle.cc14
-rw-r--r--storage/spider/spd_sys_table.cc12
-rw-r--r--storage/tokudb/ha_tokudb.cc15
-rw-r--r--storage/tokudb/ha_tokudb.h8
-rw-r--r--storage/tokudb/ha_tokudb_alter_56.cc10
-rw-r--r--storage/tokudb/ha_tokudb_alter_common.cc4
-rw-r--r--storage/tokudb/ha_tokudb_update.cc18
-rw-r--r--storage/tokudb/hatoku_cmp.cc2
-rw-r--r--storage/tokudb/hatoku_hton.cc4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/type_float.result6
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/type_ranges.result2
-rw-r--r--storage/tokudb/tokudb_dir_cmd.cc6
-rw-r--r--storage/xtradb/handler/ha_innodb.cc38
-rw-r--r--storage/xtradb/handler/ha_innodb.h4
-rw-r--r--storage/xtradb/handler/handler0alter.cc52
-rwxr-xr-xsupport-files/build-tags4
-rw-r--r--tests/mysql_client_test.c71
846 files changed, 103807 insertions, 16393 deletions
diff --git a/.gitignore b/.gitignore
index b5cc5abdb0b..c4109b63dc2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -166,6 +166,8 @@ sql/mysqld
sql/sql_builtin.cc
sql/sql_yacc.cc
sql/sql_yacc.h
+sql/sql_yacc_ora.cc
+sql/sql_yacc_ora.h
storage/heap/hp_test1
storage/heap/hp_test2
storage/maria/aria_chk
diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh
index 20784c49f0b..cae34885145 100644
--- a/BUILD/FINISH.sh
+++ b/BUILD/FINISH.sh
@@ -47,6 +47,7 @@ path=`dirname $0`
if [ -z "$just_clean" ]
then
commands="$commands
+git submodule update
CC=\"$CC\" CFLAGS=\"$cflags\" CXX=\"$CXX\" CXXFLAGS=\"$cxxflags\" CXXLDFLAGS=\"$CXXLDFLAGS\" $configure"
fi
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 42785b6dc7c..c633be6b734 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -19,6 +19,8 @@
/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
#define CHECK_VERSION "2.7.4-MariaDB"
+/* Avoid warnings from %'s format */
+#define USING_MARIADB_SNPRINTF_EXTENSIONS
#include "client_priv.h"
#include <m_ctype.h>
@@ -581,6 +583,7 @@ static int process_selected_tables(char *db, char **table_names, int tables)
my_free(table_names_comma_sep);
}
else
+ {
for (; tables > 0; tables--, table_names++)
{
table= *table_names;
@@ -590,6 +593,7 @@ static int process_selected_tables(char *db, char **table_names, int tables)
continue;
handle_request_for_tables(table, table_len, view == 1, opt_all_in_1);
}
+ }
DBUG_RETURN(0);
} /* process_selected_tables */
@@ -909,16 +913,29 @@ static int handle_request_for_tables(char *tables, size_t length,
}
break;
case DO_ANALYZE:
+ if (view)
+ {
+ printf("%-50s %s\n", tables, "Can't run anaylyze on a view");
+ DBUG_RETURN(1);
+ }
DBUG_ASSERT(!view);
op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
if (opt_persistent_all) end = strmov(end, " PERSISTENT FOR ALL");
break;
case DO_OPTIMIZE:
- DBUG_ASSERT(!view);
+ if (view)
+ {
+ printf("%-50s %s\n", tables, "Can't run optimize on a view");
+ DBUG_RETURN(1);
+ }
op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
break;
case DO_FIX_NAMES:
- DBUG_ASSERT(!view);
+ if (view)
+ {
+ printf("%-50s %s\n", tables, "Can't run fix names on a view");
+ DBUG_RETURN(1);
+ }
DBUG_RETURN(fix_table_storage_name(tables));
}
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index f8f9721d583..b036ff5645c 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1563,7 +1563,7 @@ static void make_error_message(char *buf, size_t len, const char *fmt, va_list a
fmt= "unknown error";
s+= my_vsnprintf(s, end - s, fmt, args);
- s+= my_snprintf(s, end -s, "\n", start_lineno);
+ s+= my_snprintf(s, end -s, "\n");
}
void die(const char *fmt, ...)
diff --git a/cmake/bison.cmake b/cmake/bison.cmake
index d5c725fbbde..a6a6268c644 100644
--- a/cmake/bison.cmake
+++ b/cmake/bison.cmake
@@ -40,7 +40,7 @@ ELSEIF(BISON_EXECUTABLE AND NOT BISON_USABLE)
ENDIF()
# Use bison to generate C++ and header file
-MACRO (RUN_BISON input_yy output_cc output_h)
+MACRO (RUN_BISON input_yy output_cc output_h name_prefix)
IF(BISON_TOO_OLD)
IF(EXISTS ${output_cc} AND EXISTS ${output_h})
SET(BISON_USABLE FALSE)
@@ -50,7 +50,7 @@ MACRO (RUN_BISON input_yy output_cc output_h)
ADD_CUSTOM_COMMAND(
OUTPUT ${output_cc}
${output_h}
- COMMAND ${BISON_EXECUTABLE} -y -p MYSQL
+ COMMAND ${BISON_EXECUTABLE} -y -p ${name_prefix}
--output=${output_cc}
--defines=${output_h}
${input_yy}
diff --git a/extra/comp_err.c b/extra/comp_err.c
index cf6262f66e2..5e3cec676bc 100644
--- a/extra/comp_err.c
+++ b/extra/comp_err.c
@@ -267,6 +267,7 @@ static int create_header_files(struct errors *error_head)
fprintf(sql_statef, "/* Autogenerated file, please don't edit */\n\n");
fprintf(er_namef, "/* Autogenerated file, please don't edit */\n\n");
+ fprintf(er_definef, "#ifndef ER_ERROR_FIRST\n");
fprintf(er_definef, "#define ER_ERROR_FIRST %d\n", error_head->d_code);
current_d_code= error_head->d_code -1;
@@ -314,6 +315,7 @@ static int create_header_files(struct errors *error_head)
}
/* finishing off with mysqld_error.h */
fprintf(er_definef, "#define ER_ERROR_LAST %d\n", er_last);
+ fprintf(er_definef, "#endif /* ER_ERROR_FIRST */\n");
my_fclose(er_definef, MYF(0));
my_fclose(sql_statef, MYF(0));
my_fclose(er_namef, MYF(0));
diff --git a/extra/mysqld_safe_helper.c b/extra/mysqld_safe_helper.c
index 2ccff20b910..5c50b2300d4 100644
--- a/extra/mysqld_safe_helper.c
+++ b/extra/mysqld_safe_helper.c
@@ -14,7 +14,7 @@ void my_exit(int c)
exit(c);
}
-void do_usage()
+void do_usage(void)
{
printf("Usage:\n"
" %s <user> log <filename>\n"
diff --git a/include/m_string.h b/include/m_string.h
index 8817e7faa78..f06acbea358 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -212,11 +212,6 @@ extern ulonglong strtoull(const char *str, char **ptr, int base);
#define USTRING_WITH_LEN(X) ((uchar*) X), ((size_t) (sizeof(X) - 1))
#define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1))
-struct st_mysql_const_lex_string
-{
- const char *str;
- size_t length;
-};
typedef struct st_mysql_const_lex_string LEX_CSTRING;
/* A variant with const and unsigned */
@@ -227,11 +222,17 @@ struct st_mysql_const_unsigned_lex_string
};
typedef struct st_mysql_const_unsigned_lex_string LEX_CUSTRING;
-static inline void lex_string_set(LEX_STRING *lex_str, const char *c_str)
+static inline void lex_string_set(LEX_CSTRING *lex_str, const char *c_str)
{
- lex_str->str= (char *) c_str;
+ lex_str->str= c_str;
lex_str->length= strlen(c_str);
}
+static inline void lex_string_set3(LEX_CSTRING *lex_str, const char *c_str,
+ size_t len)
+{
+ lex_str->str= c_str;
+ lex_str->length= len;
+}
#ifdef __cplusplus
static inline char *safe_str(char *str)
diff --git a/include/maria.h b/include/maria.h
index ab8fc944c8c..e25fa4c24ee 100644
--- a/include/maria.h
+++ b/include/maria.h
@@ -305,7 +305,7 @@ extern int maria_rsame(MARIA_HA *file, uchar *record, int inx);
extern int maria_rsame_with_pos(MARIA_HA *file, uchar *record,
int inx, MARIA_RECORD_POS pos);
extern int maria_update(MARIA_HA *file, const uchar *old,
- uchar *new_record);
+ const uchar *new_record);
extern int maria_write(MARIA_HA *file, uchar *buff);
extern MARIA_RECORD_POS maria_position(MARIA_HA *file);
extern int maria_status(MARIA_HA *info, MARIA_INFO *x, uint flag);
diff --git a/include/my_base.h b/include/my_base.h
index 89f5e826fd5..57b16ad985b 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -48,6 +48,8 @@
#define HA_OPEN_INTERNAL_TABLE 512U
#define HA_OPEN_NO_PSI_CALL 1024U /* Don't call/connect PSI */
#define HA_OPEN_MERGE_TABLE 2048U
+#define HA_OPEN_FOR_CREATE 4096U
+
/*
Allow opening even if table is incompatible as this is for ALTER TABLE which
will fix the table structure.
@@ -200,7 +202,9 @@ enum ha_extra_function {
HA_EXTRA_DETACH_CHILDREN,
HA_EXTRA_DETACH_CHILD,
/* Inform handler we will force a close as part of flush */
- HA_EXTRA_PREPARE_FOR_FORCED_CLOSE
+ HA_EXTRA_PREPARE_FOR_FORCED_CLOSE,
+ /* Inform handler that we will do an alter table */
+ HA_EXTRA_PREPARE_FOR_ALTER_TABLE,
};
/* Compatible option, to be deleted in 6.0 */
@@ -351,6 +355,7 @@ enum ha_base_keytype {
#define HA_CREATE_RELIES_ON_SQL_LAYER 128U
#define HA_CREATE_INTERNAL_TABLE 256U
#define HA_PRESERVE_INSERT_ORDER 512U
+#define HA_CREATE_NO_ROLLBACK 1024U
/* Flags used by start_bulk_insert */
@@ -500,7 +505,9 @@ enum ha_base_keytype {
#define HA_ERR_DECRYPTION_FAILED 192 /* Table encrypted but decypt failed */
#define HA_ERR_FK_DEPTH_EXCEEDED 193 /* FK cascade depth exceeded */
#define HA_ERR_TABLESPACE_MISSING 194 /* Missing Tablespace */
-#define HA_ERR_LAST 194 /* Copy of last error nr * */
+#define HA_ERR_SEQUENCE_INVALID_DATA 195
+#define HA_ERR_SEQUENCE_RUN_OUT 196
+#define HA_ERR_LAST 196 /* Copy of last error nr * */
/* Number of different errors */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
diff --git a/include/my_handler_errors.h b/include/my_handler_errors.h
index bdea4f71eaf..4b85832a6de 100644
--- a/include/my_handler_errors.h
+++ b/include/my_handler_errors.h
@@ -105,7 +105,9 @@ static const char *handler_error_messages[]=
"Too many words in a FTS phrase or proximity search",
"Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.",
"Foreign key cascade delete/update exceeds max depth",
- "Tablespace is missing for table"
+ "Tablespace is missing for table",
+ "Sequence has been run out",
+ "Sequence values are conflicting"
};
#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */
diff --git a/include/my_time.h b/include/my_time.h
index 90d19c8861a..02e8f32ee23 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -173,8 +173,10 @@ static inline my_bool validate_timestamp_range(const MYSQL_TIME *t)
}
/* Can't include mysqld_error.h, it needs mysys to build, thus hardcode 2 error values here. */
+#ifndef ER_WARN_DATA_OUT_OF_RANGE
#define ER_WARN_DATA_OUT_OF_RANGE 1264
#define ER_WARN_INVALID_TIMESTAMP 1299
+#endif
my_time_t
my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, uint *error_code);
diff --git a/include/myisam.h b/include/myisam.h
index f7a3ae8cc8a..dfbc00f64aa 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -275,7 +275,7 @@ extern int mi_rsame(struct st_myisam_info *file,uchar *record,int inx);
extern int mi_rsame_with_pos(struct st_myisam_info *file,uchar *record,
int inx, my_off_t pos);
extern int mi_update(struct st_myisam_info *file,const uchar *old,
- uchar *new_record);
+ const uchar *new_record);
extern int mi_write(struct st_myisam_info *file,uchar *buff);
extern my_off_t mi_position(struct st_myisam_info *file);
extern int mi_status(struct st_myisam_info *info, MI_ISAMINFO *x, uint flag);
diff --git a/include/myisammrg.h b/include/myisammrg.h
index 89293537989..952f3b02920 100644
--- a/include/myisammrg.h
+++ b/include/myisammrg.h
@@ -104,7 +104,8 @@ extern int myrg_rkey(MYRG_INFO *info,uchar *buf,int inx, const uchar *key,
key_part_map keypart_map, enum ha_rkey_function search_flag);
extern int myrg_rrnd(MYRG_INFO *file,uchar *buf,ulonglong pos);
extern int myrg_rsame(MYRG_INFO *file,uchar *record,int inx);
-extern int myrg_update(MYRG_INFO *file,const uchar *old,uchar *new_rec);
+extern int myrg_update(MYRG_INFO *file,const uchar *old,
+ const uchar *new_rec);
extern int myrg_write(MYRG_INFO *info,uchar *rec);
extern int myrg_status(MYRG_INFO *file,MYMERGE_INFO *x,int flag);
extern int myrg_lock_database(MYRG_INFO *file,int lock_type);
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 9c5d9fa4303..d061df71944 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -137,7 +137,7 @@ typedef struct st_udf_args
char **args;
unsigned long *lengths;
char *maybe_null;
- char **attributes;
+ const char **attributes;
unsigned long *attribute_lengths;
void *extension;
} UDF_ARGS;
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 03f6f0caba0..43e64c06bf1 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -178,7 +178,8 @@ extern struct my_snprintf_service_st {
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
+ ;
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
extern struct progress_report_service_st {
void (*thd_progress_init_func)(void* thd, unsigned int max_stage);
@@ -270,13 +271,20 @@ struct st_mysql_lex_string
size_t length;
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING;
extern struct thd_alloc_service_st {
void *(*thd_alloc_func)(void*, unsigned int);
void *(*thd_calloc_func)(void*, unsigned int);
char *(*thd_strdup_func)(void*, const char *);
char *(*thd_strmake_func)(void*, const char *, unsigned int);
void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(void*,
+ MYSQL_CONST_LEX_STRING *,
const char *, unsigned int, int);
} *thd_alloc_service;
void *thd_alloc(void* thd, unsigned int size);
@@ -284,9 +292,10 @@ void *thd_calloc(void* thd, unsigned int size);
char *thd_strdup(void* thd, const char *str);
char *thd_strmake(void* thd, const char *str, unsigned int size);
void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
+MYSQL_CONST_LEX_STRING
+*thd_make_lex_string(void* thd, MYSQL_CONST_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
extern struct thd_autoinc_service_st {
void (*thd_get_autoinc_func)(const void* thd,
unsigned long* off, unsigned long* inc);
diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h
index 807bfd4e652..638d9b57fd9 100644
--- a/include/mysql/plugin_auth.h
+++ b/include/mysql/plugin_auth.h
@@ -51,7 +51,7 @@ typedef struct st_mysql_server_auth_info
User name as sent by the client and shown in USER().
NULL if the client packet with the user name was not received yet.
*/
- char *user_name;
+ const char *user_name;
/**
Length of user_name
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index 07cdb1b5f52..3ee1f70ca80 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -178,7 +178,8 @@ extern struct my_snprintf_service_st {
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
+ ;
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
extern struct progress_report_service_st {
void (*thd_progress_init_func)(void* thd, unsigned int max_stage);
@@ -270,13 +271,20 @@ struct st_mysql_lex_string
size_t length;
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING;
extern struct thd_alloc_service_st {
void *(*thd_alloc_func)(void*, unsigned int);
void *(*thd_calloc_func)(void*, unsigned int);
char *(*thd_strdup_func)(void*, const char *);
char *(*thd_strmake_func)(void*, const char *, unsigned int);
void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(void*,
+ MYSQL_CONST_LEX_STRING *,
const char *, unsigned int, int);
} *thd_alloc_service;
void *thd_alloc(void* thd, unsigned int size);
@@ -284,9 +292,10 @@ void *thd_calloc(void* thd, unsigned int size);
char *thd_strdup(void* thd, const char *str);
char *thd_strmake(void* thd, const char *str, unsigned int size);
void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
+MYSQL_CONST_LEX_STRING
+*thd_make_lex_string(void* thd, MYSQL_CONST_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
extern struct thd_autoinc_service_st {
void (*thd_get_autoinc_func)(const void* thd,
unsigned long* off, unsigned long* inc);
@@ -538,7 +547,7 @@ typedef struct st_plugin_vio
} MYSQL_PLUGIN_VIO;
typedef struct st_mysql_server_auth_info
{
- char *user_name;
+ const char *user_name;
unsigned int user_name_length;
const char *auth_string;
unsigned long auth_string_length;
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index 7275f0a982e..4791846f4f2 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -178,7 +178,8 @@ extern struct my_snprintf_service_st {
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
+ ;
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
extern struct progress_report_service_st {
void (*thd_progress_init_func)(void* thd, unsigned int max_stage);
@@ -270,13 +271,20 @@ struct st_mysql_lex_string
size_t length;
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING;
extern struct thd_alloc_service_st {
void *(*thd_alloc_func)(void*, unsigned int);
void *(*thd_calloc_func)(void*, unsigned int);
char *(*thd_strdup_func)(void*, const char *);
char *(*thd_strmake_func)(void*, const char *, unsigned int);
void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(void*,
+ MYSQL_CONST_LEX_STRING *,
const char *, unsigned int, int);
} *thd_alloc_service;
void *thd_alloc(void* thd, unsigned int size);
@@ -284,9 +292,10 @@ void *thd_calloc(void* thd, unsigned int size);
char *thd_strdup(void* thd, const char *str);
char *thd_strmake(void* thd, const char *str, unsigned int size);
void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
+MYSQL_CONST_LEX_STRING
+*thd_make_lex_string(void* thd, MYSQL_CONST_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
extern struct thd_autoinc_service_st {
void (*thd_get_autoinc_func)(const void* thd,
unsigned long* off, unsigned long* inc);
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index eee69281afe..8fde9918fbc 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -178,7 +178,8 @@ extern struct my_snprintf_service_st {
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
+ ;
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
extern struct progress_report_service_st {
void (*thd_progress_init_func)(void* thd, unsigned int max_stage);
@@ -270,13 +271,20 @@ struct st_mysql_lex_string
size_t length;
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING;
extern struct thd_alloc_service_st {
void *(*thd_alloc_func)(void*, unsigned int);
void *(*thd_calloc_func)(void*, unsigned int);
char *(*thd_strdup_func)(void*, const char *);
char *(*thd_strmake_func)(void*, const char *, unsigned int);
void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(void*,
+ MYSQL_CONST_LEX_STRING *,
const char *, unsigned int, int);
} *thd_alloc_service;
void *thd_alloc(void* thd, unsigned int size);
@@ -284,9 +292,10 @@ void *thd_calloc(void* thd, unsigned int size);
char *thd_strdup(void* thd, const char *str);
char *thd_strmake(void* thd, const char *str, unsigned int size);
void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
+MYSQL_CONST_LEX_STRING
+*thd_make_lex_string(void* thd, MYSQL_CONST_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
extern struct thd_autoinc_service_st {
void (*thd_get_autoinc_func)(const void* thd,
unsigned long* off, unsigned long* inc);
diff --git a/include/mysql/plugin_password_validation.h b/include/mysql/plugin_password_validation.h
index 18c643e877b..e2763483db6 100644
--- a/include/mysql/plugin_password_validation.h
+++ b/include/mysql/plugin_password_validation.h
@@ -42,8 +42,8 @@ struct st_mariadb_password_validation
Function provided by the plugin which should perform password validation
and return 0 if the password has passed the validation.
*/
- int (*validate_password)(MYSQL_LEX_STRING *username,
- MYSQL_LEX_STRING *password);
+ int (*validate_password)(MYSQL_CONST_LEX_STRING *username,
+ MYSQL_CONST_LEX_STRING *password);
};
#ifdef __cplusplus
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index adb0afc734d..9d7717f4b32 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -178,7 +178,8 @@ extern struct my_snprintf_service_st {
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
} *my_snprintf_service;
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
+ ;
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
extern struct progress_report_service_st {
void (*thd_progress_init_func)(void* thd, unsigned int max_stage);
@@ -270,13 +271,20 @@ struct st_mysql_lex_string
size_t length;
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING;
extern struct thd_alloc_service_st {
void *(*thd_alloc_func)(void*, unsigned int);
void *(*thd_calloc_func)(void*, unsigned int);
char *(*thd_strdup_func)(void*, const char *);
char *(*thd_strmake_func)(void*, const char *, unsigned int);
void *(*thd_memdup_func)(void*, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
+ MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(void*,
+ MYSQL_CONST_LEX_STRING *,
const char *, unsigned int, int);
} *thd_alloc_service;
void *thd_alloc(void* thd, unsigned int size);
@@ -284,9 +292,10 @@ void *thd_calloc(void* thd, unsigned int size);
char *thd_strdup(void* thd, const char *str);
char *thd_strmake(void* thd, const char *str, unsigned int size);
void *thd_memdup(void* thd, const void* str, unsigned int size);
-MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
+MYSQL_CONST_LEX_STRING
+*thd_make_lex_string(void* thd, MYSQL_CONST_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
extern struct thd_autoinc_service_st {
void (*thd_get_autoinc_func)(const void* thd,
unsigned long* off, unsigned long* inc);
@@ -524,6 +533,6 @@ void thd_wakeup_subsequent_commits(void* thd, int wakeup_error);
struct st_mariadb_password_validation
{
int interface_version;
- int (*validate_password)(MYSQL_LEX_STRING *username,
- MYSQL_LEX_STRING *password);
+ int (*validate_password)(MYSQL_CONST_LEX_STRING *username,
+ MYSQL_CONST_LEX_STRING *password);
};
diff --git a/include/mysql/service_my_snprintf.h b/include/mysql/service_my_snprintf.h
index 4a99561dd00..1b2ee2ca202 100644
--- a/include/mysql/service_my_snprintf.h
+++ b/include/mysql/service_my_snprintf.h
@@ -92,9 +92,22 @@ extern struct my_snprintf_service_st {
#else
-size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
+#ifndef ATTRIBUTE_FORMAT
+#define ATTRIBUTE_FORMAT_DEFINED
+#define ATTRIBUTE_FORMAT(A,B,C)
+#endif
+#if defined(MYSQL_ABI_CHECK) || defined(USING_MARIADB_SNPRINTF_EXTENSIONS)
+#undef ATTRIBUTE_FORMAT
+#define ATTRIBUTE_FORMAT(A,B,C)
+#endif
+size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 3, 4);
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
+#ifdef ATTRIBUTE_FORMAT_DEFINED
+#undef ATTRIBUTE_FORMAT_DEFINED
+#undef ATTRIBUTE_FORMAT
+#endif
#endif
#ifdef __cplusplus
diff --git a/include/mysql/service_thd_alloc.h b/include/mysql/service_thd_alloc.h
index e92f81b52c3..8d6ed8e4190 100644
--- a/include/mysql/service_thd_alloc.h
+++ b/include/mysql/service_thd_alloc.h
@@ -42,13 +42,21 @@ struct st_mysql_lex_string
};
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_CONST_LEX_STRING;
+
extern struct thd_alloc_service_st {
void *(*thd_alloc_func)(MYSQL_THD, unsigned int);
void *(*thd_calloc_func)(MYSQL_THD, unsigned int);
char *(*thd_strdup_func)(MYSQL_THD, const char *);
char *(*thd_strmake_func)(MYSQL_THD, const char *, unsigned int);
void *(*thd_memdup_func)(MYSQL_THD, const void*, unsigned int);
- MYSQL_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD, MYSQL_LEX_STRING *,
+ MYSQL_CONST_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD,
+ MYSQL_CONST_LEX_STRING *,
const char *, unsigned int, int);
} *thd_alloc_service;
@@ -115,9 +123,10 @@ void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size);
@see thd_alloc()
*/
-MYSQL_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str,
- const char *str, unsigned int size,
- int allocate_lex_string);
+MYSQL_CONST_LEX_STRING
+*thd_make_lex_string(MYSQL_THD thd, MYSQL_CONST_LEX_STRING *lex_str,
+ const char *str, unsigned int size,
+ int allocate_lex_string);
#endif
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 06c934bf9bd..1deaa4c771c 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -645,7 +645,7 @@ typedef struct st_udf_args
char **args; /* Pointer to argument */
unsigned long *lengths; /* Length of string arguments */
char *maybe_null; /* Set to 1 for all maybe_null args */
- char **attributes; /* Pointer to attribute name */
+ const char **attributes; /* Pointer to attribute name */
unsigned long *attribute_lengths; /* Length of attribute arguments */
void *extension;
} UDF_ARGS;
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 5516cd7013a..6dabc5e0192 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -30,6 +30,8 @@ ${SSL_INTERNAL_INCLUDE_DIRS}
SET(GEN_SOURCES
${CMAKE_BINARY_DIR}/sql/sql_yacc.h
${CMAKE_BINARY_DIR}/sql/sql_yacc.cc
+${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.h
+${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.cc
${CMAKE_BINARY_DIR}/sql/lex_hash.h
)
@@ -111,6 +113,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/wsrep_dummy.cc ../sql/encryption.cc
../sql/item_windowfunc.cc ../sql/sql_window.cc
../sql/sql_cte.cc
+ ../sql/sql_sequence.cc ../sql/sql_sequence.h
+ ../sql/ha_sequence.cc ../sql/ha_sequence.h
../sql/temporary_tables.cc
../sql/session_tracker.cc
${GEN_SOURCES}
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 555eadc9425..5883061f24f 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -742,7 +742,7 @@ emb_transfer_connect_attrs(MYSQL *mysql)
int check_embedded_connection(MYSQL *mysql, const char *db)
{
int result;
- LEX_STRING db_str = { (char*)db, db ? strlen(db) : 0 };
+ LEX_CSTRING db_str = { db, safe_strlen(db) };
THD *thd= (THD*)mysql->thd;
/* the server does the same as the client */
@@ -1046,12 +1046,14 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
strlen(server_field.db_name), cs, thd_cs);
client_field->table= dup_str_aux(field_alloc, server_field.table_name,
strlen(server_field.table_name), cs, thd_cs);
- client_field->name= dup_str_aux(field_alloc, server_field.col_name,
- strlen(server_field.col_name), cs, thd_cs);
+ client_field->name= dup_str_aux(field_alloc, server_field.col_name.str,
+ server_field.col_name.length, cs, thd_cs);
client_field->org_table= dup_str_aux(field_alloc, server_field.org_table_name,
strlen(server_field.org_table_name), cs, thd_cs);
- client_field->org_name= dup_str_aux(field_alloc, server_field.org_col_name,
- strlen(server_field.org_col_name), cs, thd_cs);
+ client_field->org_name= dup_str_aux(field_alloc,
+ server_field.org_col_name.str,
+ server_field.org_col_name.length,
+ cs, thd_cs);
if (item->charset_for_protocol() == &my_charset_bin || thd_cs == NULL)
{
/* No conversion */
diff --git a/mysql-test/extra/rpl_tests/rpl_charset.test b/mysql-test/extra/rpl_tests/rpl_charset.test
index 37ca2e28eec..e67122cbb4c 100644
--- a/mysql-test/extra/rpl_tests/rpl_charset.test
+++ b/mysql-test/extra/rpl_tests/rpl_charset.test
@@ -117,4 +117,32 @@ update t1 set pk='test' where pk=@p;
drop table t1;
# End of 4.1 tests
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+
+--echo #
+--echo # MDEV-12685 Oracle-compatible function CHR()
+--echo #
+
+connection master;
+CREATE DATABASE db1 DEFAULT CHARACTER SET latin1 COLLATE latin1_bin;
+USE db1;
+CREATE TABLE t1 AS SELECT CHR(0x60);
+sync_slave_with_master;
+SHOW CREATE TABLE db1.t1;
+connection master;
+USE test;
+DROP DATABASE db1;
+sync_slave_with_master;
+
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
+
+
--source include/rpl_end.inc
diff --git a/mysql-test/include/gis_generic.inc b/mysql-test/include/gis_generic.inc
index 59acf04dfa2..8209240614e 100644
--- a/mysql-test/include/gis_generic.inc
+++ b/mysql-test/include/gis_generic.inc
@@ -236,7 +236,7 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index b132e90752b..c0b26f41b71 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -171,6 +171,7 @@ my @DEFAULT_SUITES= qw(
binlog-
binlog_encryption-
csv-
+ compat/oracle-
encryption-
federated-
funcs_1-
@@ -194,6 +195,7 @@ my @DEFAULT_SUITES= qw(
roles-
rpl-
sys_vars-
+ sql_sequence-
unit-
vcol-
wsrep-
@@ -4260,7 +4262,7 @@ sub extract_server_log ($$) {
push(@lines, $line);
if (scalar(@lines) > 1000000) {
$Ferr = undef;
- mtr_warning("Too much log from test, bailing out from extracting");
+ mtr_warning("Too much log in $error_log, bailing out from extracting");
return ();
}
}
diff --git a/mysql-test/r/analyze_format_json.result b/mysql-test/r/analyze_format_json.result
index 307fb734026..7991379bc55 100644
--- a/mysql-test/r/analyze_format_json.result
+++ b/mysql-test/r/analyze_format_json.result
@@ -451,6 +451,7 @@ ANALYZE
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
diff --git a/mysql-test/r/bug13633383.result b/mysql-test/r/bug13633383.result
index a6f5bab5260..ed94ec5b98b 100644
--- a/mysql-test/r/bug13633383.result
+++ b/mysql-test/r/bug13633383.result
@@ -45,70 +45,6 @@ repeat('a',10000) desc,
repeat('a',10000)
with rollup
;
-col435
-0.00000000000000000
-0.00000000000000000
-0.00000000000000000
-Warnings:
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0'
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00'
+ERROR HY000: Illegal parameter data types int and geometry for operation '='
set session sort_buffer_size= default;
DROP TABLE t1, t2, t3;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index ab6ae5e6a5a..3214f52e765 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -387,3 +387,63 @@ DROP TABLE t1;
#
# End of 10.1 test
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
+#
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT
+CASE -1
+WHEN -9223372036854775808 THEN 'one'
+ WHEN 18446744073709551615 THEN 'two'
+ END AS c;
+c
+NULL
+PREPARE stmt FROM "SELECT
+ CASE -1
+ WHEN -9223372036854775808 THEN 'one'
+ WHEN 18446744073709551615 THEN 'two'
+ END AS c";
+EXECUTE stmt;
+c
+NULL
+EXECUTE stmt;
+c
+NULL
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+#
+# MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
+#
+SELECT
+CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ END AS good,
+CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
+ END AS was_bad_now_good;
+good was_bad_now_good
+one one
+PREPARE stmt FROM "SELECT
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ END AS good,
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
+ END AS was_bad_now_good";
+EXECUTE stmt;
+good was_bad_now_good
+one one
+EXECUTE stmt;
+good was_bad_now_good
+one one
+DEALLOCATE PREPARE stmt;
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 13ce2e53367..3c9cbb18bcb 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -762,7 +762,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`CONCAT(CAST(REPEAT('9', 1000) AS SIGNED))` varchar(21) NOT NULL,
- `CONCAT(CAST(REPEAT('9', 1000) AS UNSIGNED))` varchar(21) NOT NULL
+ `CONCAT(CAST(REPEAT('9', 1000) AS UNSIGNED))` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
# End of test for Bug#13581962, Bug#14096619
@@ -900,3 +900,271 @@ t1 CREATE TABLE `t1` (
`CONCAT(CONVERT('',UNSIGNED))` varchar(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
+#
+# MDEV-12849 Out-of-range errors when casting hex-hybrid to SIGNED and UNSIGNED
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE PROCEDURE p1(hh TEXT)
+BEGIN
+EXECUTE IMMEDIATE
+CONCAT('CREATE OR REPLACE TABLE t1 AS SELECT CAST(0x', hh, ' AS UNSIGNED) AS c');
+DESCRIBE t1;
+SELECT c, LENGTH(c) FROM t1;
+DROP TABLE t1;
+EXECUTE IMMEDIATE
+CONCAT('CREATE OR REPLACE TABLE t1 AS SELECT CAST(0x', hh, ' AS SIGNED) AS c');
+DESCRIBE t1;
+SELECT c, LENGTH(c) FROM t1;
+DROP TABLE t1;
+SELECT '' AS `------`;
+END
+$$
+CALL p1('FF');
+Field Type Null Key Default Extra
+c int(3) unsigned NO NULL
+c LENGTH(c)
+255 3
+Field Type Null Key Default Extra
+c int(3) NO NULL
+c LENGTH(c)
+255 3
+------
+
+CALL p1('FFFF');
+Field Type Null Key Default Extra
+c int(5) unsigned NO NULL
+c LENGTH(c)
+65535 5
+Field Type Null Key Default Extra
+c int(5) NO NULL
+c LENGTH(c)
+65535 5
+------
+
+CALL p1('FFFFFF');
+Field Type Null Key Default Extra
+c int(8) unsigned NO NULL
+c LENGTH(c)
+16777215 8
+Field Type Null Key Default Extra
+c int(8) NO NULL
+c LENGTH(c)
+16777215 8
+------
+
+CALL p1('FFFFFFFF');
+Field Type Null Key Default Extra
+c int(10) unsigned NO NULL
+c LENGTH(c)
+4294967295 10
+Field Type Null Key Default Extra
+c bigint(10) NO NULL
+c LENGTH(c)
+4294967295 10
+------
+
+CALL p1('FFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(13) unsigned NO NULL
+c LENGTH(c)
+1099511627775 13
+Field Type Null Key Default Extra
+c bigint(13) NO NULL
+c LENGTH(c)
+1099511627775 13
+------
+
+CALL p1('FFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(15) unsigned NO NULL
+c LENGTH(c)
+281474976710655 15
+Field Type Null Key Default Extra
+c bigint(15) NO NULL
+c LENGTH(c)
+281474976710655 15
+------
+
+CALL p1('FFFFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(17) unsigned NO NULL
+c LENGTH(c)
+72057594037927935 17
+Field Type Null Key Default Extra
+c bigint(17) NO NULL
+c LENGTH(c)
+72057594037927935 17
+------
+
+CALL p1('FFFFFFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+18446744073709551615 20
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-1 2
+------
+
+CALL p1('FFFFFFFFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+18446744073709551615 20
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-1 2
+------
+
+CALL p1('FFFFFFFFFFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+18446744073709551615 20
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-1 2
+------
+
+CALL p1('8000000000000000');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223372036854775808 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223372036854775808 20
+------
+
+CALL p1('80000000000000FF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223372036854776063 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223372036854775553 20
+------
+
+CALL p1('800000000000FFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223372036854841343 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223372036854710273 20
+------
+
+CALL p1('8000000000FFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223372036871553023 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223372036837998593 20
+------
+
+CALL p1('80000000FFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223372041149743103 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223372032559808513 20
+------
+
+CALL p1('800000FFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223373136366403583 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223370937343148033 20
+------
+
+CALL p1('8000FFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9223653511831486463 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9223090561878065153 20
+------
+
+CALL p1('80FFFFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+9295429630892703743 19
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-9151314442816847873 20
+------
+
+CALL p1('8FFFFFFFFFFFFFFF');
+Field Type Null Key Default Extra
+c bigint(20) unsigned NO NULL
+c LENGTH(c)
+10376293541461622783 20
+Field Type Null Key Default Extra
+c bigint(20) NO NULL
+c LENGTH(c)
+-8070450532247928833 20
+------
+
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+#
+# MDEV-12852 Out-of-range errors when CAST(1-2 AS UNSIGNED
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT
+CAST(-1 AS UNSIGNED),
+CAST(1-2 AS UNSIGNED);
+Warnings:
+Note 1105 Cast to unsigned converted negative integer to it's positive complement
+Note 1105 Cast to unsigned converted negative integer to it's positive complement
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CAST(-1 AS UNSIGNED)` bigint(20) unsigned NOT NULL,
+ `CAST(1-2 AS UNSIGNED)` bigint(20) unsigned NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+CAST(-1 AS UNSIGNED) CAST(1-2 AS UNSIGNED)
+18446744073709551615 18446744073709551615
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# MDEV-12853 Out-of-range errors when CAST('-1' AS UNSIGNED
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT CAST('-1' AS UNSIGNED);
+Warnings:
+Note 1105 Cast to unsigned converted negative integer to it's positive complement
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CAST('-1' AS UNSIGNED)` bigint(20) unsigned NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+CAST('-1' AS UNSIGNED)
+18446744073709551615
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/r/commit_1innodb.result b/mysql-test/r/commit_1innodb.result
index 1adba7b4c4c..61274fa9049 100644
--- a/mysql-test/r/commit_1innodb.result
+++ b/mysql-test/r/commit_1innodb.result
@@ -230,6 +230,7 @@ insert into t2 (a) values (1023);
do (f2(23));
Warnings:
Error 1062 Duplicate entry '23' for key 'a'
+Note 4070 At line 4 in test.f2
select * from t2;
a
1023
diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index ea8111cc3ce..b4a6b22ba3a 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -88,7 +88,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,<expr_cache><`test`.`t2`.`a`>((select count(0) from `test`.`t1` where `test`.`t1`.`b` = `test`.`t2`.`a` and concat(`test`.`t1`.`b`,`test`.`t1`.`c`) = concat('0',`test`.`t2`.`a`,'01'))) AS `x` from `test`.`t2` order by `test`.`t2`.`a`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,<expr_cache><`test`.`t2`.`a`>((/* select#2 */ select count(0) from `test`.`t1` where `test`.`t1`.`b` = `test`.`t2`.`a` and concat(`test`.`t1`.`b`,`test`.`t1`.`c`) = concat('0',`test`.`t2`.`a`,'01'))) AS `x` from `test`.`t2` order by `test`.`t2`.`a`
DROP TABLE t1,t2;
CREATE TABLE t1 (a TIMESTAMP);
INSERT INTO t1 VALUES (NOW()),(NOW()),(NOW());
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 81b65c420cd..dca48c07fe9 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -482,19 +482,41 @@ from t1;
explain t2;
Field Type Null Key Default Extra
a int(11) YES NULL
-b bigint(11) NO NULL
-c bigint(10) unsigned NO NULL
+b int(11) NO NULL
+c int(10) unsigned NO NULL
d date YES NULL
e varchar(1) YES NULL
f datetime YES NULL
g time YES NULL
-h longblob YES NULL
+h blob YES NULL
dd time YES NULL
select * from t2;
a b c d e f g h dd
1 -7 7 2000-01-01 b 2000-01-01 00:00:00 05:04:03 yet another binary data 02:00:00
2 -2 2 1825-12-14 a 2003-01-01 03:02:01 04:03:02 binary data 02:00:00
drop table t1, t2;
+CREATE TABLE t1 (
+c_tinytext tinytext,
+c_text text,
+c_mediumtext mediumtext,
+c_longtext longtext
+);
+CREATE TABLE t2 AS SELECT
+ifnull(c_tinytext, CAST('yet another binary data' AS BINARY)),
+ifnull(c_text, CAST('yet another binary data' AS BINARY)),
+ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY)),
+ifnull(c_longtext, CAST('yet another binary data' AS BINARY))
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `ifnull(c_tinytext, CAST('yet another binary data' AS BINARY))` tinyblob DEFAULT NULL,
+ `ifnull(c_text, CAST('yet another binary data' AS BINARY))` blob DEFAULT NULL,
+ `ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY))` mediumblob DEFAULT NULL,
+ `ifnull(c_longtext, CAST('yet another binary data' AS BINARY))` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10));
create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnull(e,e), ifnull(f,f), ifnull(g,g), ifnull(h,h), ifnull(i,i), ifnull(j,j), ifnull(k,k), ifnull(l,l), ifnull(m,m), ifnull(n,n), ifnull(o,o) from t1;
show create table t2;
@@ -645,7 +667,7 @@ create table t1 (a int);
create table t1 select * from t1;
ERROR 42S01: Table 't1' already exists
create table t2 union = (t1) select * from t1;
-ERROR HY000: 'test.t2' is not BASE TABLE
+ERROR HY000: 'test.t2' is not of type 'BASE TABLE'
flush tables with read lock;
unlock tables;
drop table t1;
@@ -679,7 +701,7 @@ create database mysqltest;
use mysqltest;
create view v1 as select 'foo' from dual;
create table t1 like v1;
-ERROR HY000: 'mysqltest.v1' is not BASE TABLE
+ERROR HY000: 'mysqltest.v1' is not of type 'BASE TABLE'
drop view v1;
drop database mysqltest;
create database mysqltest;
@@ -1351,7 +1373,7 @@ CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
BEGIN
UPDATE A SET `pk`=1 WHERE `pk`=0 ;
END ;|
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.f' already exists
CREATE TRIGGER f1 BEFORE INSERT ON t1 FOR EACH ROW
BEGIN
UPDATE A SET `pk`=1 WHERE `pk`=0 ;
diff --git a/mysql-test/r/create_drop_binlog.result b/mysql-test/r/create_drop_binlog.result
index 249f99475be..dc9c1da2c14 100644
--- a/mysql-test/r/create_drop_binlog.result
+++ b/mysql-test/r/create_drop_binlog.result
@@ -160,7 +160,7 @@ Note 1050 Table 'v1' already exists
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
# # Format_desc 1 # VER
@@ -274,7 +274,7 @@ DROP TRIGGER tr1;
CREATE TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=20;
CREATE TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=21;
Warnings:
-Note 1359 Trigger already exists
+Note 1359 Trigger 'test.tr1' already exists
DROP TRIGGER IF EXISTS tr1;
DROP TRIGGER IF EXISTS tr1;
Warnings:
diff --git a/mysql-test/r/create_drop_trigger.result b/mysql-test/r/create_drop_trigger.result
index f7ae8d21a7f..d2857a0cb79 100644
--- a/mysql-test/r/create_drop_trigger.result
+++ b/mysql-test/r/create_drop_trigger.result
@@ -10,7 +10,7 @@ SELECT @sum;
CREATE TRIGGER IF NOT EXISTS val_sum_new BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val;
CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + 1 + NEW.val;
Warnings:
-Note 1359 Trigger already exists
+Note 1359 Trigger 'db1.val_sum' already exists
CREATE OR REPLACE TRIGGER IF NOT EXISTS val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 2 + NEW.val;
ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
@@ -21,7 +21,7 @@ SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val
ACTION_STATEMENT
SET @sum = @sum + 3 + NEW.val
CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 4 + NEW.val;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'db1.val_sum' already exists
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
ACTION_STATEMENT
SET @sum = @sum + 3 + NEW.val
diff --git a/mysql-test/r/create_drop_view.result b/mysql-test/r/create_drop_view.result
index 0ec337b9b25..117f7b851c6 100644
--- a/mysql-test/r/create_drop_view.result
+++ b/mysql-test/r/create_drop_view.result
@@ -55,5 +55,5 @@ id
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
DROP TABLE t1;
diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result
index 79d380a04db..2fceebd1971 100644
--- a/mysql-test/r/cte_nonrecursive.result
+++ b/mysql-test/r/cte_nonrecursive.result
@@ -705,7 +705,7 @@ ERROR 42S21: Duplicate column name 'f1'
with t as (select * from t2 where c>3),
t as (select a from t1 where a>2)
select * from t,t1 where t1.a=t.c;
-ERROR HY000: Duplicate query name in WITH clause
+ERROR HY000: Duplicate query name `t` in WITH clause
with t as (select a from s where a<5),
s as (select a from t1 where b>='d')
select * from t,s where t.a=s.a;
diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result
index 42ba01e42de..946ba16ac5c 100644
--- a/mysql-test/r/cte_recursive.result
+++ b/mysql-test/r/cte_recursive.result
@@ -130,7 +130,7 @@ select t2.a+1 from t1,t2 where t1.a=t2.a
select * from t1;
show columns from v1;
Field Type Null Key Default Extra
-a bigint(20) YES NULL
+a bigint(12) YES NULL
# WITH RECURSIVE : types of t1 columns are determined by anchor parts
create view v2 as
with recursive
@@ -699,7 +699,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4,5> ALL NULL NULL NULL NULL NULL NULL
2 UNCACHEABLE SUBQUERY <derived3> ALL NULL NULL NULL NULL 12 100.00 Using where
Warnings:
-Note 1003 with recursive ancestor_couple_ids as (select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors as (select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where `test`.`p`.`id` = `ma`.`w_id`)select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id`
+Note 1003 with recursive ancestor_couple_ids as (/* select#2 */ select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors as (/* select#3 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all /* select#4 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all /* select#5 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where `test`.`p`.`id` = `ma`.`w_id`)/* select#1 */ select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id`
# simple mutual recursion
with recursive
ancestor_couple_ids(h_id, w_id)
@@ -882,7 +882,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 with recursive ancestors as (select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' and `test`.`folks`.`dob` = DATE'2000-01-01' union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestors` `a` where `a`.`father` = `p`.`id` or `a`.`mother` = `p`.`id`)select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors`
+Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' and `test`.`folks`.`dob` = DATE'2000-01-01' union /* select#3 */ select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestors` `a` where `a`.`father` = `p`.`id` or `a`.`mother` = `p`.`id`)/* select#1 */ select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors`
# recursive spec with two anchor selects and two recursive ones
with recursive
ancestor_ids (id)
@@ -1353,6 +1353,7 @@ EXPLAIN
{
"query_block": {
"select_id": 4,
+ "operation": "UNION",
"table": {
"table_name": "folks",
"access_type": "ALL",
@@ -1365,6 +1366,7 @@ EXPLAIN
{
"query_block": {
"select_id": 6,
+ "operation": "UNION",
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
@@ -1380,6 +1382,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "folks",
"access_type": "ALL",
@@ -1392,6 +1395,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "folks",
"access_type": "ALL",
@@ -1423,6 +1427,7 @@ EXPLAIN
{
"query_block": {
"select_id": 5,
+ "operation": "UNION",
"table": {
"table_name": "<derived4>",
"access_type": "ALL",
@@ -1484,6 +1489,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "v",
"access_type": "ALL",
@@ -1518,6 +1524,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "<derived4>",
"access_type": "ALL",
@@ -1750,6 +1757,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -1761,6 +1769,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
@@ -2378,6 +2387,7 @@ ANALYZE
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"message": "No tables used"
}
@@ -2386,6 +2396,7 @@ ANALYZE
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"r_loops": 10,
"r_total_time_ms": "REPLACED",
"table": {
diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result
index 976c3df6e0e..0afe5298411 100644
--- a/mysql-test/r/ctype_binary.result
+++ b/mysql-test/r/ctype_binary.result
@@ -382,7 +382,7 @@ create table t1 as select concat(sign(0.5)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(21) DEFAULT NULL
+ `c1` varbinary(2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as select concat(rand()) as c1;
@@ -419,7 +419,7 @@ create table t1 as select concat(bit_length('a')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(10) DEFAULT NULL
+ `c1` varbinary(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(coercibility('a')));
@@ -469,7 +469,7 @@ create table t1 as select concat(ord(61)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(21) DEFAULT NULL
+ `c1` varbinary(7) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(find_in_set('b','a,b,c,d')));
@@ -608,7 +608,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(2) DEFAULT NULL
+ `c1` varbinary(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
@@ -618,7 +618,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(2) DEFAULT NULL
+ `c1` varbinary(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
@@ -696,7 +696,7 @@ create table t1 as select concat(sleep(0)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(21) DEFAULT NULL
+ `c1` varbinary(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(is_free_lock('xxxx')));
@@ -1447,7 +1447,7 @@ create table t1 as select concat(microsecond('12:00:00.123456')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varbinary(21) DEFAULT NULL
+ `c1` varbinary(6) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(month(20090224)));
@@ -3037,7 +3037,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a'
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a'
DROP TABLE t1;
#
# End of MDEV-8694
@@ -3070,7 +3070,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a), CRC32(a) FROM t1 WHERE a='a' AND CRC32(a)=
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)`,crc32(`test`.`t1`.`a`) AS `CRC32(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a'
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)`,crc32(`test`.`t1`.`a`) AS `CRC32(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a'
SELECT a, HEX(a) FROM t1 WHERE HEX(a)='61';
a HEX(a)
a 61
diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result
index d4f75778ace..5799331f73e 100644
--- a/mysql-test/r/ctype_cp1250_ch.result
+++ b/mysql-test/r/ctype_cp1250_ch.result
@@ -220,7 +220,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
DROP TABLE t1;
#
# End of MDEV-8694
diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result
index 037f3cb07e3..fabd7fa484c 100644
--- a/mysql-test/r/ctype_cp1251.result
+++ b/mysql-test/r/ctype_cp1251.result
@@ -791,7 +791,7 @@ create table t1 as select concat(sign(0.5)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(2) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as select concat(rand()) as c1;
@@ -828,7 +828,7 @@ create table t1 as select concat(bit_length('a')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(10) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(11) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(coercibility('a')));
@@ -878,7 +878,7 @@ create table t1 as select concat(ord(61)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(7) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(find_in_set('b','a,b,c,d')));
@@ -1017,7 +1017,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
@@ -1027,7 +1027,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
@@ -1105,7 +1105,7 @@ create table t1 as select concat(sleep(0)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(is_free_lock('xxxx')));
@@ -1856,7 +1856,7 @@ create table t1 as select concat(microsecond('12:00:00.123456')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET cp1251 DEFAULT NULL
+ `c1` varchar(6) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(month(20090224)));
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index fc37dcfda8b..94b25849a2a 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -1088,7 +1088,7 @@ create table t1 as select concat(sign(0.5)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) DEFAULT NULL
+ `c1` varchar(2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as select concat(rand()) as c1;
@@ -1125,7 +1125,7 @@ create table t1 as select concat(bit_length('a')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(10) DEFAULT NULL
+ `c1` varchar(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(coercibility('a')));
@@ -1175,7 +1175,7 @@ create table t1 as select concat(ord(61)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) DEFAULT NULL
+ `c1` varchar(7) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(find_in_set('b','a,b,c,d')));
@@ -1314,7 +1314,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) DEFAULT NULL
+ `c1` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
@@ -1324,7 +1324,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) DEFAULT NULL
+ `c1` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
@@ -1402,7 +1402,7 @@ create table t1 as select concat(sleep(0)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) DEFAULT NULL
+ `c1` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(is_free_lock('xxxx')));
@@ -2153,7 +2153,7 @@ create table t1 as select concat(microsecond('12:00:00.123456')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) DEFAULT NULL
+ `c1` varchar(6) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(month(20090224)));
@@ -7817,7 +7817,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
@@ -7938,7 +7938,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
@@ -8160,7 +8160,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a), CRC32(a) FROM t1 WHERE a='a' AND CRC32(a)=
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)`,crc32(`test`.`t1`.`a`) AS `CRC32(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and crc32(`test`.`t1`.`a`) = 3904355907
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)`,crc32(`test`.`t1`.`a`) AS `CRC32(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and crc32(`test`.`t1`.`a`) = 3904355907
SELECT a, HEX(a) FROM t1 WHERE HEX(a)='61';
a HEX(a)
a 61
@@ -8188,7 +8188,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='a' AND LENGTH(a)=2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a' and length(`test`.`t1`.`a`) = 2
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a' and octet_length(`test`.`t1`.`a`) = 2
DROP TABLE t1;
#
# MDEV-8712 Wrong result for SELECT..WHERE latin1_bin_column=_latin1'a' AND latin1_bin_column='A'
diff --git a/mysql-test/r/ctype_latin2_ch.result b/mysql-test/r/ctype_latin2_ch.result
index 87357a49197..a396bc77fb6 100644
--- a/mysql-test/r/ctype_latin2_ch.result
+++ b/mysql-test/r/ctype_latin2_ch.result
@@ -160,7 +160,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
diff --git a/mysql-test/r/ctype_tis620.result b/mysql-test/r/ctype_tis620.result
index d5b4c632c31..cf66c81c647 100644
--- a/mysql-test/r/ctype_tis620.result
+++ b/mysql-test/r/ctype_tis620.result
@@ -3230,7 +3230,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
@@ -3446,7 +3446,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result
index 6c6dceba9cb..725e744c44e 100644
--- a/mysql-test/r/ctype_uca.result
+++ b/mysql-test/r/ctype_uca.result
@@ -8547,7 +8547,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
DROP TABLE t1;
#
# End of MDEV-8694
@@ -8705,7 +8705,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
DROP TABLE t1;
#
# End of MDEV-8694
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 08af0186080..5b914258515 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -1967,7 +1967,7 @@ create table t1 as select concat(sign(0.5)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as select concat(rand()) as c1;
@@ -2004,7 +2004,7 @@ create table t1 as select concat(bit_length('a')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(10) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(11) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(coercibility('a')));
@@ -2054,7 +2054,7 @@ create table t1 as select concat(ord(61)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(7) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(find_in_set('b','a,b,c,d')));
@@ -2193,7 +2193,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
@@ -2203,7 +2203,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
@@ -2281,7 +2281,7 @@ create table t1 as select concat(sleep(0)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(is_free_lock('xxxx')));
@@ -3032,7 +3032,7 @@ create table t1 as select concat(microsecond('12:00:00.123456')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET ucs2 DEFAULT NULL
+ `c1` varchar(6) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(month(20090224)));
@@ -5465,7 +5465,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
@@ -5586,7 +5586,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 0a4898ff0b9..532bfa6d9e5 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -2839,7 +2839,7 @@ create table t1 as select concat(sign(0.5)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(2) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as select concat(rand()) as c1;
@@ -2876,7 +2876,7 @@ create table t1 as select concat(bit_length('a')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(11) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(coercibility('a')));
@@ -2926,7 +2926,7 @@ create table t1 as select concat(ord(61)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(7) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(find_in_set('b','a,b,c,d')));
@@ -3065,7 +3065,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
@@ -3075,7 +3075,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(2) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
@@ -3153,7 +3153,7 @@ create table t1 as select concat(sleep(0)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(is_free_lock('xxxx')));
@@ -3904,7 +3904,7 @@ create table t1 as select concat(microsecond('12:00:00.123456')) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` varchar(21) CHARACTER SET utf8 DEFAULT NULL
+ `c1` varchar(6) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(month(20090224)));
@@ -6918,7 +6918,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a '
DROP TABLE t1;
#
# End of MDEV-8694
@@ -7039,7 +7039,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
+Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a'
DROP TABLE t1;
#
# End of MDEV-8694
@@ -11174,3 +11174,31 @@ SET STORAGE_ENGINE=Default;
#
# End of 10.2 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-11155 Bad error message when creating a SET column with comma and non-ASCII characters
+#
+SET NAMES utf8;
+CREATE TABLE t1 (a SET('a,bü'));
+ERROR 22007: Illegal set 'a,bü' value found during parsing
+#
+# MDEV-12607 Hybrid functions create wrong VARBINARY length when mixing character and binary data
+#
+SET sql_mode='';
+SET NAMES utf8;
+CREATE OR REPLACE TABLE t1 AS SELECT COALESCE('ßa',_binary 'a');
+SELECT * FROM t1;
+COALESCE('ßa',_binary 'a')
+ßa
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `COALESCE('ßa',_binary 'a')` varbinary(6) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result
index 2780ed3b168..c18db932afa 100644
--- a/mysql-test/r/default.result
+++ b/mysql-test/r/default.result
@@ -1035,14 +1035,9 @@ t1 CREATE TABLE `t1` (
`a` decimal(30,6) DEFAULT coalesce(current_timestamp(6))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES();
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
INSERT IGNORE INTO t1 VALUES();
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
SET sql_mode = 'STRICT_ALL_TABLES';
INSERT INTO t1 VALUES();
-ERROR 01000: Data truncated for column 'a' at row 1
SET sql_mode = DEFAULT;
DROP TABLE t1;
#
@@ -1055,8 +1050,6 @@ t1 CREATE TABLE `t1` (
`a` decimal(30,6) DEFAULT coalesce(curtime(6))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT IGNORE INTO t1 VALUES();
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
DROP TABLE t1;
#
# DECIMAL + CURRENT_DATE, no truncation
@@ -1068,8 +1061,6 @@ t1 CREATE TABLE `t1` (
`a` decimal(30,6) DEFAULT coalesce(curdate())
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT IGNORE INTO t1 VALUES();
-Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
DROP TABLE t1;
#
# COALESCE for SQL Standard <datetime value function>
@@ -1126,10 +1117,10 @@ t1 CREATE TABLE `t1` (
INSERT IGNORE INTO t1 VALUES ();
Warnings:
Note 1265 Data truncated for column 'a' at row 1
-Warning 1265 Data truncated for column 'b' at row 1
+Note 1265 Data truncated for column 'b' at row 1
SELECT * FROM t1;
a b
-20010101102030 2001
+20010101102030 20010101102030
DROP TABLE t1;
#
# Check DEFAULT() function
@@ -2910,7 +2901,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) DEFAULT length(`a`),
+ `b` int(11) DEFAULT octet_length(`a`),
`c` int(11) DEFAULT char_length(`a`),
`d` int(11) DEFAULT bit_length(`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
diff --git a/mysql-test/r/delete_use_source.result b/mysql-test/r/delete_use_source.result
new file mode 100644
index 00000000000..7886caf6ba4
--- /dev/null
+++ b/mysql-test/r/delete_use_source.result
@@ -0,0 +1,151 @@
+create table t1(c1 integer not null,c2 integer not null, key (c1)) engine=InnoDb;
+create view v1 as select * from t1 where c1 in (0,1);
+insert t1 select 0,seq from seq_1_to_500;
+insert t1 select 1,seq from seq_1_to_50;
+insert t1 select 2,seq from seq_1_to_20;
+insert t1 select 3,seq from seq_1_to_20;
+#
+# Delete with limit (quick select - range acces)
+#
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
+affected rows: 1
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
+affected rows: 0
+select count(*) from v1 where c1=0;
+count(*)
+499
+rollback;
+#
+# Delete
+#
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 ;
+affected rows: 500
+rollback;
+#
+# Delete with exists
+#
+start transaction;
+select count(*) from v1 where c1=2;
+count(*)
+0
+delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
+affected rows: 20
+delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
+affected rows: 0
+select count(*) from v1 where c1=2;
+count(*)
+0
+rollback;
+#
+# Delete throw a view with limit (range access)
+#
+start transaction;
+explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range c1 c1 4 NULL 550 Using where
+2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 82 Using index
+delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
+affected rows: 1
+delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
+affected rows: 0
+select count(*) from v1 where c1=0;
+count(*)
+499
+rollback;
+#
+# Delete throw a view (ALL access)
+#
+start transaction;
+explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL c1 NULL NULL NULL 717 Using where
+2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 82 Using index
+delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ;
+affected rows: 500
+select count(*) from v1 where c1=0;
+count(*)
+0
+rollback;
+#
+# Delete failed due to trigger
+#
+create trigger trg after delete on t1 for each row
+begin
+declare c int;
+begin
+if old.c1 = 1 then
+select count(*) into c from t1 where c1!=old.c1;
+SIGNAL SQLSTATE '45000' set table_name=c;
+end if;
+end;
+end;
+/
+start transaction;
+delete from t1 where c1=1 and (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c2 asc limit 10;
+ERROR 45000: Unhandled user-defined exception condition
+rollback;
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c1 desc limit 100;
+ERROR 45000: Unhandled user-defined exception condition
+select c1,count(*) from t1 group by c1;
+c1 count(*)
+0 500
+1 50
+2 20
+3 20
+rollback;
+drop trigger trg;
+#
+# Delete throw a view with returning
+#
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 asc limit 10 returning c1,c2;
+c1 c2
+0 1
+0 2
+0 3
+0 4
+0 5
+0 6
+0 7
+0 8
+0 9
+0 10
+rollback;
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 desc limit 10 returning c1,c2;
+c1 c2
+0 491
+0 492
+0 493
+0 494
+0 495
+0 496
+0 497
+0 498
+0 499
+0 500
+rollback;
+drop view v1;
+drop table t1;
+#
+# Delete from table with more than 150000 rows
+#
+create table t1(c1 integer not null,c2 integer not null, key (c1));
+insert t1 select 0,seq from seq_1_to_128000;
+insert t1 select 1,seq from seq_1_to_25600;
+select count(*) from t1;
+count(*)
+153600
+# with a lot of memory for sort_buffer_size
+set session sort_buffer_size = 1024000;
+delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
+affected rows: 128000
+# with little memory for sort_buffer_size
+insert t1 select 0,seq from seq_1_to_128000;
+set session sort_buffer_size = 1024;
+delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
+affected rows: 128000
+drop table t1;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 722ff76e556..220fd5a8c74 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -632,7 +632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 system NULL NULL NULL NULL 1 100.00
Warnings:
Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 6 AS `f1` from <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `test`.`t2`.`f3` = 6 and `<subquery4>`.`f3` = 9
+Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `test`.`t2`.`f3` = 6 and `<subquery4>`.`f3` = 9
DROP TABLE t2,t1;
#
# MDEV-9462: Out of memory using explain on 2 empty tables
diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result
index b94cb46acea..5b07b0488e0 100644
--- a/mysql-test/r/derived_cond_pushdown.result
+++ b/mysql-test/r/derived_cond_pushdown.result
@@ -4111,6 +4111,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "t2",
"access_type": "ALL",
@@ -4254,6 +4255,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "t2",
"access_type": "ALL",
@@ -4408,6 +4410,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "t2",
"access_type": "ALL",
@@ -4564,6 +4567,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "t2",
"access_type": "ALL",
@@ -4607,6 +4611,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "t2",
"access_type": "ALL",
@@ -4730,6 +4735,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"having_condition": "c < 300 and c > 100",
"filesort": {
"sort_key": "t1.a, t1.b",
@@ -4838,6 +4844,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"having_condition": "c < 300 and (t1.a < 2 or c > 800)",
"filesort": {
"sort_key": "t1.a, t1.b",
@@ -4933,6 +4940,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"having_condition": "c < 300 and c < 200",
"filesort": {
"sort_key": "t1.b",
@@ -5130,6 +5138,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"having_condition": "c < 300",
"filesort": {
"sort_key": "t1.b",
@@ -5234,6 +5243,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"having_condition": "c < 300 and c > 200",
"filesort": {
"sort_key": "t1.a, t1.b",
@@ -5252,6 +5262,7 @@ EXPLAIN
{
"query_block": {
"select_id": 4,
+ "operation": "UNION",
"having_condition": "c < 707 and c > 200",
"filesort": {
"sort_key": "t1.a, t1.b",
@@ -5395,6 +5406,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -5512,6 +5524,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -5597,6 +5610,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -5685,6 +5699,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -5792,6 +5807,7 @@ EXPLAIN
{
"query_block": {
"select_id": 3,
+ "operation": "UNION",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -6996,7 +7012,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 2 100.00 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select `sq1`.`f` AS `f` from (select min(`test`.`t1`.`i`) AS `f` from `test`.`t1` having `f` = 8) `sq1` where `sq1`.`f` = 8
+Note 1003 /* select#1 */ select `sq1`.`f` AS `f` from (/* select#3 */ select min(`test`.`t1`.`i`) AS `f` from `test`.`t1` having `f` = 8) `sq1` where `sq1`.`f` = 8
SELECT *
FROM ( SELECT * FROM ( SELECT MIN(i) as f FROM t1 ) sq1 ) AS sq2
WHERE f = 8;
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index df6ba084a87..9221c6240bd 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -194,7 +194,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` group by `test`.`t1`.`f1`) `tt`
+Note 1003 /* select#1 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#2 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` group by `test`.`t1`.`f1`) `tt`
select * from (select * from t1 having f1=f1) tt;
f1 f11
1 1
@@ -216,7 +216,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`tt`.`f2` AS `f2`,`tt`.`f22` AS `f22` from `test`.`t1` join (select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` group by `test`.`t2`.`f2`) `tt` where `tt`.`f2` = `test`.`t1`.`f1`
+Note 1003 /* select#1 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`tt`.`f2` AS `f2`,`tt`.`f22` AS `f22` from `test`.`t1` join (/* select#2 */ select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` group by `test`.`t2`.`f2`) `tt` where `tt`.`f2` = `test`.`t1`.`f1`
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
f1 f11 f2 f22
1 1 1 1
@@ -269,7 +269,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1`
+Note 1003 /* select#1 */ select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1`
select * from v1;
f1 f11
1 1
@@ -290,7 +290,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`v2`.`f2` AS `f2`,`v2`.`f22` AS `f22` from `test`.`t1` join `test`.`v2` where `v2`.`f2` = `test`.`t1`.`f1`
+Note 1003 /* select#1 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`v2`.`f2` AS `f2`,`v2`.`f22` AS `f22` from `test`.`t1` join `test`.`v2` where `v2`.`f2` = `test`.`t1`.`f1`
select * from t1 join v2 on f1=f2;
f1 f11 f2 f22
1 1 1 1
@@ -307,7 +307,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t11 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`v31`.`f1` AS `f1`,`v31`.`f11` AS `f11`,`v3`.`f1` AS `f1`,`v3`.`f11` AS `f11` from `test`.`t1` join `test`.`v3` `v31` join `test`.`v3` where `v31`.`f1` = `test`.`t1`.`f1` and `v3`.`f1` = `test`.`t1`.`f1`
+Note 1003 /* select#1 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`v31`.`f1` AS `f1`,`v31`.`f11` AS `f11`,`v3`.`f1` AS `f1`,`v3`.`f11` AS `f11` from `test`.`t1` join `test`.`v3` `v31` join `test`.`v3` where `v31`.`f1` = `test`.`t1`.`f1` and `v3`.`f1` = `test`.`t1`.`f1`
flush status;
select * from t1,v3 as v31,v3 where t1.f1=v31.f1 and t1.f1=v3.f1;
f1 f11 f1 f11 f1 f11
@@ -374,7 +374,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ref key0 key0 5 test.t2.f2 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`v1` join `test`.`t2` where `v1`.`f1` = `test`.`t2`.`f2` and `test`.`t2`.`f2` in (2,3)
+Note 1003 /* select#1 */ select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`v1` join `test`.`t2` where `v1`.`f1` = `test`.`t2`.`f2` and `test`.`t2`.`f2` in (2,3)
explain format=json select * from v1 join v4 on f1=f2;
EXPLAIN
{
@@ -440,7 +440,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` where `tt`.`f1` > 2
+Note 1003 /* select#1 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#3 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` where `tt`.`f1` > 2
select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2) zz;
f1 f11
@@ -453,7 +453,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `zz`.`f1` AS `f1`,`zz`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` > 2 and `test`.`t1`.`f1` < 7 group by `test`.`t1`.`f1`) `zz`
+Note 1003 /* select#1 */ select `zz`.`f1` AS `f1`,`zz`.`f11` AS `f11` from (/* select#2 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` > 2 and `test`.`t1`.`f1` < 7 group by `test`.`t1`.`f1`) `zz`
select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2 group by f1) zz;
f1 f11
@@ -467,7 +467,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `zz`.`f1` AS `f1`,`zz`.`f11` AS `f11` from (select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` where `tt`.`f1` > 2 group by `tt`.`f1`) `zz`
+Note 1003 /* select#1 */ select `zz`.`f1` AS `f1`,`zz`.`f11` AS `f11` from (/* select#2 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#3 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` where `tt`.`f1` > 2 group by `tt`.`f1`) `zz`
explain format=json select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) zz;
EXPLAIN
@@ -533,7 +533,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
5 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11`,`tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` join (select `t1`.`f1` AS `f1`,`t1`.`f11` AS `f11` from `test`.`t1` where `t1`.`f1` < 7 and `t1`.`f1` > 2 and `t1`.`f1` > 2 group by `t1`.`f1`) `tt` where `tt`.`f1` = `tt`.`f1` and `tt`.`f1` > 2 and `tt`.`f1` > 2
+Note 1003 /* select#1 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11`,`tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#3 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` join (/* select#5 */ select `t1`.`f1` AS `f1`,`t1`.`f11` AS `f11` from `test`.`t1` where `t1`.`f1` < 7 and `t1`.`f1` > 2 and `t1`.`f1` > 2 group by `t1`.`f1`) `tt` where `tt`.`f1` = `tt`.`f1` and `tt`.`f1` > 2 and `tt`.`f1` > 2
explain format=json select * from
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) x
join
@@ -658,7 +658,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `x`.`f1` AS `f1`,`x`.`f11` AS `f11`,`z`.`f1` AS `f1`,`z`.`f11` AS `f11` from (select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` where `tt`.`f1` > 2 group by `tt`.`f1`) `x` join (select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `t1`.`f1` AS `f1`,`t1`.`f11` AS `f11` from `test`.`t1` where `t1`.`f1` < 7 and `t1`.`f1` > 2 group by `t1`.`f1`) `tt` where `tt`.`f1` > 2 group by `tt`.`f1`) `z` where `z`.`f1` = `x`.`f1`
+Note 1003 /* select#1 */ select `x`.`f1` AS `f1`,`x`.`f11` AS `f11`,`z`.`f1` AS `f1`,`z`.`f11` AS `f11` from (/* select#2 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#3 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where `test`.`t1`.`f1` < 7 and `test`.`t1`.`f1` > 2 group by `test`.`t1`.`f1`) `tt` where `tt`.`f1` > 2 group by `tt`.`f1`) `x` join (/* select#4 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#5 */ select `t1`.`f1` AS `f1`,`t1`.`f11` AS `f11` from `test`.`t1` where `t1`.`f1` < 7 and `t1`.`f1` > 2 group by `t1`.`f1`) `tt` where `tt`.`f1` > 2 group by `tt`.`f1`) `z` where `z`.`f1` = `x`.`f1`
explain format=json select * from
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) x
@@ -775,7 +775,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `tt`.`f2` AS `f2`,`tt`.`f22` AS `f22` from (select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` where `test`.`t2`.`f2` in (2,3) group by 1) `tt`
+Note 1003 /* select#1 */ select `tt`.`f2` AS `f2`,`tt`.`f22` AS `f22` from (/* select#2 */ select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` where `test`.`t2`.`f2` in (2,3) group by 1) `tt`
select * from (select * from v4 group by 1) tt;
f2 f22
2 2
@@ -787,7 +787,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1` where `v1`.`f1` < 7
+Note 1003 /* select#1 */ select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1` where `v1`.`f1` < 7
explain format=json
select * from ( select * from v1 where f1 < 7) tt;
EXPLAIN
@@ -845,7 +845,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED <derived4> ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
4 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1` group by 1) `tt`
+Note 1003 /* select#1 */ select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (/* select#2 */ select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1` group by 1) `tt`
select * from (select * from v7 group by 1) tt;
f1 f11
1 1
@@ -866,7 +866,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived5> ref key0 key0 5 test.t2.f2 2 100.00
5 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22`,`v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`t2` join `test`.`v1` where `v1`.`f1` = `test`.`t2`.`f2` and `test`.`t2`.`f2` < 7 and `test`.`t2`.`f2` in (2,3)
+Note 1003 /* select#1 */ select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22`,`v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`t2` join `test`.`v1` where `v1`.`f1` = `test`.`t2`.`f2` and `test`.`t2`.`f2` < 7 and `test`.`t2`.`f2` in (2,3)
explain format=json select * from v6 join v7 on f2=f1;
EXPLAIN
{
@@ -1143,7 +1143,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
3 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <expr_cache><`test`.`t3`.`a`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select `v1`.`a` from `test`.`v1` join `test`.`t2` where `test`.`t2`.`a` = `v1`.`b` and <cache>(`test`.`t3`.`a`) = `v1`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <expr_cache><`test`.`t3`.`a`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `v1`.`a` from `test`.`v1` join `test`.`t2` where `test`.`t2`.`a` = `v1`.`b` and <cache>(`test`.`t3`.`a`) = `v1`.`a`)))
SELECT * FROM t3
WHERE t3.a IN (SELECT v1.a FROM v1, t2 WHERE t2.a = v1.b);
a
@@ -1437,7 +1437,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select 6 AS `a`,5 AS `b` from `test`.`t3` where 1
+Note 1003 /* select#1 */ select 6 AS `a`,5 AS `b` from `test`.`t3` where 1
SELECT t.a,t.b FROM t3 RIGHT JOIN ((SELECT * FROM t1) AS t, t2) ON t2.b != 0
WHERE (t.a,t.b) NOT IN (SELECT 7, 5);
a b
@@ -1451,7 +1451,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00
3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select 6 AS `a`,5 AS `b` from `test`.`t3` where 1
+Note 1003 /* select#1 */ select 6 AS `a`,5 AS `b` from `test`.`t3` where 1
SELECT t.a,t.b FROM t3 RIGHT JOIN (v1 AS t, t2) ON t2.b != 0
WHERE (t.a,t.b) NOT IN (SELECT 7, 5);
a b
@@ -1465,7 +1465,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1 100.00
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select 6 AS `a`,5 AS `b` from `test`.`t3` where 1
+Note 1003 /* select#1 */ select 6 AS `a`,5 AS `b` from `test`.`t3` where 1
DROP VIEW v1;
DROP TABLE t1,t2,t3;
#
@@ -1559,7 +1559,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
3 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `v2`.`b` AS `b` from `test`.`v2` where 0
+Note 1003 /* select#1 */ select `v2`.`b` AS `b` from `test`.`v2` where 0
DROP VIEW v1,v2;
DROP TABLE t1;
#
@@ -1624,7 +1624,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 't.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(1,<expr_cache><`test`.`t1`.`a`>(exists(select 28 from `test`.`t3` where 'j' < `test`.`t1`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(1,<expr_cache><`test`.`t1`.`a`>(exists(/* select#3 */ select 28 from `test`.`t3` where 'j' < `test`.`t1`.`a`)))
SELECT * FROM (SELECT * FROM t1) AS t
WHERE EXISTS (SELECT t2.a FROM t3 RIGHT JOIN t2 ON (t3.a = t2.a)
WHERE t2.b < t.a);
@@ -2522,7 +2522,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ref key0 key0 5 test.t2.c2 2 100.00 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v1`.`c1` AS `c1`,`v1`.`c2` AS `c2` from `test`.`v1` join `test`.`t2` where `v1`.`c1` = `test`.`t2`.`c1` and `v1`.`c2` = `test`.`t2`.`c2`
+Note 1003 /* select#1 */ select `v1`.`c1` AS `c1`,`v1`.`c2` AS `c2` from `test`.`v1` join `test`.`t2` where `v1`.`c1` = `test`.`t2`.`c1` and `v1`.`c2` = `test`.`t2`.`c2`
SELECT v1.c1, v1.c2 FROM v1, t2 WHERE v1.c1=t2.c1 AND v1.c2=t2.c2;
c1 c2
c 3
@@ -2535,7 +2535,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ref key0 key0 5 test.t2.c2 2 100.00 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `test`.`t2`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2` from (select `test`.`t1`.`c1` AS `g`,max(`test`.`t1`.`c2`) AS `m` from `test`.`t1` group by `test`.`t1`.`c1`) `t` join `test`.`t2` where `t`.`g` = `test`.`t2`.`c1` and `t`.`m` = `test`.`t2`.`c2`
+Note 1003 /* select#1 */ select `test`.`t2`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2` from (/* select#2 */ select `test`.`t1`.`c1` AS `g`,max(`test`.`t1`.`c2`) AS `m` from `test`.`t1` group by `test`.`t1`.`c1`) `t` join `test`.`t2` where `t`.`g` = `test`.`t2`.`c1` and `t`.`m` = `test`.`t2`.`c2`
SELECT t2.c1, t2.c2 FROM (SELECT c1 g, MAX(c2) m FROM t1 GROUP BY c1) t, t2
WHERE t.g=t2.c1 AND t.m=t2.c2;
c1 c2
@@ -2547,7 +2547,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v1`.`c1` AS `c1`,`v1`.`c2` AS `c2`,`test`.`t2`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2` from `test`.`v1` join `test`.`t2` where `v1`.`c1` = `test`.`t2`.`c1`
+Note 1003 /* select#1 */ select `v1`.`c1` AS `c1`,`v1`.`c2` AS `c2`,`test`.`t2`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2` from `test`.`v1` join `test`.`t2` where `v1`.`c1` = `test`.`t2`.`c1`
SELECT v1.c1, v1.c2, t2.c1, t2.c2 FROM v1, t2 WHERE v1.c1=t2.c1;
c1 c2 c1 c2
c 3 c 3
@@ -2973,7 +2973,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select straight_join `test`.`t1`.`c1` AS `c1` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t2`.`c2` from `test`.`t2` where <cache>(`test`.`t1`.`c1`) = `test`.`t2`.`c2`))
+Note 1003 /* select#1 */ select straight_join `test`.`t1`.`c1` AS `c1` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#3 */ select `test`.`t2`.`c2` from `test`.`t2` where <cache>(`test`.`t1`.`c1`) = `test`.`t2`.`c2`))
DROP TABLE t1, t2;
set optimizer_switch=@exit_optimizer_switch;
set join_cache_level=@exit_join_cache_level;
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 8d7074cd270..926dc17d0c4 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -920,7 +920,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 96 100.00 Using where
Warnings:
-Note 1003 select straight_join distinct `test`.`t1`.`id` AS `id` from `test`.`t1` join `test`.`v1` join `test`.`t2` where `test`.`t2`.`i` = `v1`.`id` and `v1`.`i1` = `test`.`t1`.`i1` and `v1`.`id` <> 3
+Note 1003 /* select#1 */ select straight_join distinct `test`.`t1`.`id` AS `id` from `test`.`t1` join `test`.`v1` join `test`.`t2` where `test`.`t2`.`i` = `v1`.`id` and `v1`.`i1` = `test`.`t1`.`i1` and `v1`.`id` <> 3
set join_buffer_size=1024;
SELECT STRAIGHT_JOIN DISTINCT t1.id FROM
t1, v1, t2 WHERE v1.id = t2.i AND t1.i1 = v1.i1 AND t2.i != 3;
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index 1a06380e66f..f33a482dc0b 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -198,7 +198,7 @@ ERROR 42S02: Unknown table 'test.table1'
DROP TABLE table1,table2;
ERROR 42S02: Unknown table 'test.table1,test.table2'
DROP VIEW view1,view2,view3,view4;
-ERROR 42S02: Unknown table 'test.view1,test.view2,test.view3,test.view4'
+ERROR 42S02: Unknown VIEW: 'test.view1,test.view2,test.view3,test.view4'
DROP TABLE IF EXISTS table1;
Warnings:
@@ -209,10 +209,10 @@ Note 1051 Unknown table 'test.table1'
Note 1051 Unknown table 'test.table2'
DROP VIEW IF EXISTS view1,view2,view3,view4;
Warnings:
-Note 1051 Unknown table 'test.view1'
-Note 1051 Unknown table 'test.view2'
-Note 1051 Unknown table 'test.view3'
-Note 1051 Unknown table 'test.view4'
+Note 4068 Unknown VIEW: 'test.view1'
+Note 4068 Unknown VIEW: 'test.view2'
+Note 4068 Unknown VIEW: 'test.view3'
+Note 4068 Unknown VIEW: 'test.view4'
# Test error message when trigger does not find table
CREATE TABLE table1(a int);
diff --git a/mysql-test/r/errors.result b/mysql-test/r/errors.result
index 6e88ad00ad9..e7a315f4314 100644
--- a/mysql-test/r/errors.result
+++ b/mysql-test/r/errors.result
@@ -32,8 +32,6 @@ set sql_mode=default;
CREATE TABLE t1 (a INT);
SELECT a FROM t1 WHERE a IN(1, (SELECT IF(1=0,1,2/0)));
a
-Warnings:
-Warning 1365 Division by 0
INSERT INTO t1 VALUES(1);
SELECT a FROM t1 WHERE a IN(1, (SELECT IF(1=0,1,2/0)));
a
diff --git a/mysql-test/r/except.result b/mysql-test/r/except.result
new file mode 100644
index 00000000000..fdaa625ea65
--- /dev/null
+++ b/mysql-test/r/except.result
@@ -0,0 +1,527 @@
+create table t1 (a int, b int) engine=MyISAM;
+create table t2 (c int, d int) engine=MyISAM;
+insert into t1 values (1,1),(2,2);
+insert into t2 values (2,2),(3,3);
+(select a,b from t1) except (select c,d from t2);
+a b
+1 1
+EXPLAIN (select a,b from t1) except (select c,d from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2
+2 EXCEPT t2 ALL NULL NULL NULL NULL 2
+NULL EXCEPT RESULT <except1,2> ALL NULL NULL NULL NULL NULL
+EXPLAIN extended (select a,b from t1) except (select c,d from t2);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 EXCEPT t2 ALL NULL NULL NULL NULL 2 100.00
+NULL EXCEPT RESULT <except1,2> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) except (/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)
+EXPLAIN extended select * from ((select a,b from t1) except (select c,d from t2)) a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00
+3 EXCEPT t2 ALL NULL NULL NULL NULL 2 100.00
+NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a`
+EXPLAIN format=json (select a,b from t1) except (select c,d from t2);
+EXPLAIN
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<except1,2>",
+ "access_type": "ALL",
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "EXCEPT",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json (select a,b from t1) except (select c,d from t2);
+ANALYZE
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<except1,2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 1,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "EXCEPT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json select * from ((select a,b from t1) except (select c,d from t2)) a;
+ANALYZE
+{
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 1,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100,
+ "materialized": {
+ "query_block": {
+ "union_result": {
+ "table_name": "<except2,3>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 1,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "operation": "EXCEPT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
+select * from ((select a,b from t1) except (select c,d from t2)) a;
+a b
+1 1
+prepare stmt from "(select a,b from t1) except (select c,d from t2)";
+execute stmt;
+a b
+1 1
+execute stmt;
+a b
+1 1
+prepare stmt from "select * from ((select a,b from t1) except (select c,d from t2)) a";
+execute stmt;
+a b
+1 1
+execute stmt;
+a b
+1 1
+drop tables t1,t2;
+create table t1 (a int, b int) engine=MyISAM;
+create table t2 (c int, d int) engine=MyISAM;
+create table t3 (e int, f int) engine=MyISAM;
+create table t4 (g int, h int) engine=MyISAM;
+insert into t1 values (1,1),(2,2);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (4,4),(5,5);
+insert into t4 values (4,4),(7,7);
+(select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+a b e f
+1 1 4 4
+1 1 5 5
+2 2 5 5
+EXPLAIN (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+2 EXCEPT t2 ALL NULL NULL NULL NULL 2
+2 EXCEPT t4 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+NULL EXCEPT RESULT <except1,2> ALL NULL NULL NULL NULL NULL
+EXPLAIN (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+2 EXCEPT t2 ALL NULL NULL NULL NULL 2
+2 EXCEPT t4 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+NULL EXCEPT RESULT <except1,2> ALL NULL NULL NULL NULL NULL
+EXPLAIN extended select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t3 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
+3 EXCEPT t2 ALL NULL NULL NULL NULL 2 100.00
+3 EXCEPT t4 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
+NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a`
+EXPLAIN format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+EXPLAIN
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<except1,2>",
+ "access_type": "ALL",
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL"
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "EXCEPT",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t4",
+ "access_type": "ALL",
+ "rows": 2,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL"
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+ANALYZE
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<except1,2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 3,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL",
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "EXCEPT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t4",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL",
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json select * from ((select a,b,e,f from t1,t3) except
+(select c,d,g,h from t2,t4)) a;
+ANALYZE
+{
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 4,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100,
+ "materialized": {
+ "query_block": {
+ "union_result": {
+ "table_name": "<except2,3>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 3,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL",
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "operation": "EXCEPT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t4",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 2,
+ "r_rows": 2,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL",
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
+select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a;
+a b e f
+1 1 4 4
+1 1 5 5
+2 2 5 5
+prepare stmt from "(select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)";
+execute stmt;
+a b e f
+1 1 4 4
+1 1 5 5
+2 2 5 5
+execute stmt;
+a b e f
+1 1 4 4
+1 1 5 5
+2 2 5 5
+prepare stmt from "select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a";
+execute stmt;
+a b e f
+1 1 4 4
+1 1 5 5
+2 2 5 5
+execute stmt;
+a b e f
+1 1 4 4
+1 1 5 5
+2 2 5 5
+drop tables t1,t2,t3,t4;
+select 1 as a from dual except select 1 from dual;
+a
+(select 1 from dual) except (select 1 from dual);
+1
+(select 1 from dual into @v) except (select 1 from dual);
+ERROR HY000: Incorrect usage of EXCEPT and INTO
+select 1 from dual ORDER BY 1 except select 1 from dual;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'except select 1 from dual' at line 1
+select 1 as a from dual union all select 1 from dual;
+a
+1
+1
+select 1 from dual except all select 1 from dual;
+ERROR HY000: Incorrect usage of EXCEPT and ALL
+create table t1 (a int, b blob, a1 int, b1 blob) engine=MyISAM;
+create table t2 (c int, d blob, c1 int, d1 blob) engine=MyISAM;
+insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt");
+insert into t2 values (2, "fgh", 2, "dffggtt"),(3, "ffggddd", 3, "dfgg");
+(select a,b,b1 from t1) except (select c,d,d1 from t2);
+a b b1
+1 ddd sdfrrwwww
+create table t3 (select a,b,b1 from t1) except (select c,d,d1 from t2);
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` int(11) DEFAULT NULL,
+ `b` blob DEFAULT NULL,
+ `b1` blob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop tables t1,t2,t3;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index 6d73f1ac4d6..97e49af96d4 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -158,7 +158,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
EXPLAIN EXTENDED SELECT 1
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -166,7 +166,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
prepare s1 from
'EXPLAIN EXTENDED SELECT 1
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
@@ -176,7 +176,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
prepare s1 from
'EXPLAIN EXTENDED SELECT 1
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
@@ -186,14 +186,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
execute s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT PRIMARY KEY);
EXPLAIN EXTENDED SELECT COUNT(a) FROM t1 USE KEY(a);
@@ -221,7 +221,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 SUBQUERY t system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 0
SET SESSION sql_mode=@old_sql_mode;
DROP TABLE t1;
End of 5.0 tests.
@@ -268,7 +268,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
-Note 1003 select (select 1 from `test`.`t2` where `test`.`t2`.`d` = NULL) AS `(SELECT 1 FROM t2 WHERE d = c)` from dual
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from `test`.`t2` where `test`.`t2`.`d` = NULL) AS `(SELECT 1 FROM t2 WHERE d = c)` from dual
DROP TABLE t1, t2;
#
# Bug#30302: Tables that were optimized away are printed in the
@@ -390,7 +390,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select NULL AS `a` from (select NULL AS `a` from `test`.`t1` where 0) `t`
+Note 1003 /* select#1 */ select NULL AS `a` from (/* select#2 */ select NULL AS `a` from `test`.`t1` where 0) `t`
set optimizer_switch=@tmp_optimizer_switch;
DROP TABLE t1,t2;
#
diff --git a/mysql-test/r/explain_json.result b/mysql-test/r/explain_json.result
index 1e95e983253..a64d4af5890 100644
--- a/mysql-test/r/explain_json.result
+++ b/mysql-test/r/explain_json.result
@@ -229,6 +229,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "B",
"access_type": "ALL",
@@ -263,6 +264,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
+ "operation": "UNION",
"table": {
"table_name": "B",
"access_type": "ALL",
diff --git a/mysql-test/r/flush-innodb.result b/mysql-test/r/flush-innodb.result
index bd09f0d62dc..21e5bda7785 100644
--- a/mysql-test/r/flush-innodb.result
+++ b/mysql-test/r/flush-innodb.result
@@ -60,7 +60,7 @@ DROP TABLE export;
CREATE VIEW v1 AS SELECT 1;
CREATE TEMPORARY TABLE t1 (a INT);
FLUSH TABLES v1 FOR EXPORT;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
FLUSH TABLES t1 FOR EXPORT;
ERROR 42S02: Table 'test.t1' doesn't exist
FLUSH TABLES non_existent FOR EXPORT;
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index 2c651b71a66..5cd4fde477d 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -295,16 +295,16 @@ create view v1 as select 1;
create view v2 as select * from t1;
create view v3 as select * from v2;
flush table v1, v2, v3 with read lock;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
flush table v1 with read lock;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
flush table v2 with read lock;
-ERROR HY000: 'test.v2' is not BASE TABLE
+ERROR HY000: 'test.v2' is not of type 'BASE TABLE'
flush table v3 with read lock;
-ERROR HY000: 'test.v3' is not BASE TABLE
+ERROR HY000: 'test.v3' is not of type 'BASE TABLE'
create temporary table v1 (a int);
flush table v1 with read lock;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
drop view v1;
create table v1 (a int);
flush table v1 with read lock;
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index 6857813559f..60ddd866507 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -22,7 +22,7 @@ explain extended select uncompressed_length(compress(@test_compress_string))=len
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select uncompressed_length(compress(@`test_compress_string`)) = length(@`test_compress_string`) AS `uncompressed_length(compress(@test_compress_string))=length(@test_compress_string)`
+Note 1003 select uncompressed_length(compress(@`test_compress_string`)) = octet_length(@`test_compress_string`) AS `uncompressed_length(compress(@test_compress_string))=length(@test_compress_string)`
select uncompressed_length(compress(@test_compress_string));
uncompressed_length(compress(@test_compress_string))
117
diff --git a/mysql-test/r/func_debug.result b/mysql-test/r/func_debug.result
new file mode 100644
index 00000000000..f55bfca80f5
--- /dev/null
+++ b/mysql-test/r/func_debug.result
@@ -0,0 +1,1657 @@
+SET SESSION debug_dbug="+d,Item_func_in";
+SET SESSION debug_dbug="+d,Predicant_to_list_comparator";
+# Constant predicant, compatible types, bisect
+SELECT 1 IN (1,2);
+1 IN (1,2)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 IN (1,2,NULL);
+1 IN (1,2,NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 NOT IN (1,2);
+1 NOT IN (1,2)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 NOT IN (1,2,NULL);
+1 NOT IN (1,2,NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1.0 IN (1.0,2.0);
+1.0 IN (1.0,2.0)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1.0 IN (1.0,2.0,NULL);
+1.0 IN (1.0,2.0,NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1.0 NOT IN (1.0,2.0);
+1.0 NOT IN (1.0,2.0)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1.0 NOT IN (1.0,2.0,NULL);
+1.0 NOT IN (1.0,2.0,NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1e0 IN (1e0,2e0);
+1e0 IN (1e0,2e0)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1e0 IN (1e0,2e0,NULL);
+1e0 IN (1e0,2e0,NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1e0 NOT IN (1e0,2e0);
+1e0 NOT IN (1e0,2e0)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1e0 NOT IN (1e0,2e0,NULL);
+1e0 NOT IN (1e0,2e0,NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 'a' IN ('a','b');
+'a' IN ('a','b')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 'a' IN ('a','b',NULL);
+'a' IN ('a','b',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 'a' NOT IN ('a','b');
+'a' NOT IN ('a','b')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 'a' NOT IN ('a','b',NULL);
+'a' NOT IN ('a','b',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30');
+TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL);
+TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30');
+TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL);
+TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' IN ('10:20:30','10:20:30');
+TIME'10:20:30' IN ('10:20:30','10:20:30')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' IN ('10:20:30','10:20:30',NULL);
+TIME'10:20:30' IN ('10:20:30','10:20:30',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' NOT IN ('10:20:30','10:20:30');
+TIME'10:20:30' NOT IN ('10:20:30','10:20:30')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' NOT IN ('10:20:30','10:20:30',NULL);
+TIME'10:20:30' NOT IN ('10:20:30','10:20:30',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT DATE'2001-01-01' IN ('2001-01-01','2001-02-02');
+DATE'2001-01-01' IN ('2001-01-01','2001-02-02')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT DATE'2001-01-01' IN ('2001-01-01','2001-02-02',NULL);
+DATE'2001-01-01' IN ('2001-01-01','2001-02-02',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02');
+DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02',NULL);
+DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+# Column predicant, compatible types, bisect
+CREATE TABLE t1 (a INT UNSIGNED);
+SELECT a IN (1.0, 1) FROM t1;
+a IN (1.0, 1)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+SELECT a IN (1,2,3) FROM t1;
+a IN (1,2,3)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN (1,2,3,NULL) FROM t1;
+a IN (1,2,3,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN (1.0, CAST(1 AS UNSIGNED)) FROM t1;
+a IN (1.0, CAST(1 AS UNSIGNED))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN (1.0, CAST(1 AS UNSIGNED),NULL) FROM t1;
+a IN (1.0, CAST(1 AS UNSIGNED),NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1,2,3) FROM t1;
+a NOT IN (1,2,3)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1,2,3,NULL) FROM t1;
+a NOT IN (1,2,3,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1.0, CAST(1 AS UNSIGNED)) FROM t1;
+a NOT IN (1.0, CAST(1 AS UNSIGNED))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1.0, CAST(1 AS UNSIGNED),NULL) FROM t1;
+a NOT IN (1.0, CAST(1 AS UNSIGNED),NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a DOUBLE);
+SELECT a IN (1e0,2,3.0) FROM t1;
+a IN (1e0,2,3.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN (1e0,2,3.0,NULL) FROM t1;
+a IN (1e0,2,3.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1e0,2,3.0) FROM t1;
+a NOT IN (1e0,2,3.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1e0,2,3.0,NULL) FROM t1;
+a NOT IN (1e0,2,3.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a DECIMAL(10,1));
+SELECT a IN (1,2.0,3.0) FROM t1;
+a IN (1,2.0,3.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN (1,2.0,3.0,NULL) FROM t1;
+a IN (1,2.0,3.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1,2.0,3.0) FROM t1;
+a NOT IN (1,2.0,3.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN (1,2.0,3.0,NULL) FROM t1;
+a NOT IN (1,2.0,3.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10));
+SELECT a IN ('a','b','c') FROM t1;
+a IN ('a','b','c')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN ('a','b','c',NULL) FROM t1;
+a IN ('a','b','c',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('a','b','c') FROM t1;
+a NOT IN ('a','b','c')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('a','b','c',NULL) FROM t1;
+a NOT IN ('a','b','c',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a DATE);
+SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1;
+a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: [2] arg=3 handler=0 (date)
+Note 1105 DBUG: [3] arg=4 handler=0 (date)
+Note 1105 DBUG: [4] arg=5 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1;
+a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: [2] arg=3 handler=0 (date)
+Note 1105 DBUG: [3] arg=4 handler=0 (date)
+Note 1105 DBUG: [4] arg=5 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1;
+a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: [2] arg=3 handler=0 (date)
+Note 1105 DBUG: [3] arg=4 handler=0 (date)
+Note 1105 DBUG: [4] arg=5 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1;
+a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: [2] arg=3 handler=0 (date)
+Note 1105 DBUG: [3] arg=4 handler=0 (date)
+Note 1105 DBUG: [4] arg=5 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a TIME);
+SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1;
+a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=0 (time)
+Note 1105 DBUG: [4] arg=5 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1;
+a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=0 (time)
+Note 1105 DBUG: [4] arg=5 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1;
+a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=0 (time)
+Note 1105 DBUG: [4] arg=5 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1;
+a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=0 (time)
+Note 1105 DBUG: [4] arg=5 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a DATETIME);
+SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1;
+a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
+Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
+Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
+Note 1105 DBUG: [5] arg=6 handler=0 (datetime)
+Note 1105 DBUG: [6] arg=7 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1;
+a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
+Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
+Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
+Note 1105 DBUG: [5] arg=6 handler=0 (datetime)
+Note 1105 DBUG: [6] arg=7 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1;
+a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
+Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
+Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
+Note 1105 DBUG: [5] arg=6 handler=0 (datetime)
+Note 1105 DBUG: [6] arg=7 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1;
+a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
+Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
+Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
+Note 1105 DBUG: [5] arg=6 handler=0 (datetime)
+Note 1105 DBUG: [6] arg=7 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+# Constant predicant, compatible types, no bisect
+# Bisect is not used because of non-constant expressions in the list
+CREATE TABLE t1 (a INT);
+SELECT 1 IN (a,1,2,3) FROM t1;
+1 IN (a,1,2,3)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: [3] arg=4 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 IN (a,1,2,3,NULL) FROM t1;
+1 IN (a,1,2,3,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: [3] arg=4 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 NOT IN (a,1,2,3) FROM t1;
+1 NOT IN (a,1,2,3)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: [3] arg=4 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 NOT IN (a,1,2,3,NULL) FROM t1;
+1 NOT IN (a,1,2,3,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=0 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (bigint)
+Note 1105 DBUG: [3] arg=4 handler=0 (bigint)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a DOUBLE);
+SELECT 1 IN (a,1e0,2e0,3e0) FROM t1;
+1 IN (a,1e0,2e0,3e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: [3] arg=4 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 IN (a,1e0,2e0,3e0,NULL) FROM t1;
+1 IN (a,1e0,2e0,3e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: [3] arg=4 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 NOT IN (a,1e0,2e0,3e0) FROM t1;
+1 NOT IN (a,1e0,2e0,3e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: [3] arg=4 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 NOT IN (a,1e0,2e0,3e0,NULL) FROM t1;
+1 NOT IN (a,1e0,2e0,3e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=0 (double)
+Note 1105 DBUG: [2] arg=3 handler=0 (double)
+Note 1105 DBUG: [3] arg=4 handler=0 (double)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a DECIMAL(10,1));
+SELECT 1 IN (a,1.0,2.0,3.0) FROM t1;
+1 IN (a,1.0,2.0,3.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: [3] arg=4 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 IN (a,1.0,2.0,3.0,NULL) FROM t1;
+1 IN (a,1.0,2.0,3.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: [3] arg=4 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 NOT IN (a,1.0,2.0,3.0) FROM t1;
+1 NOT IN (a,1.0,2.0,3.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: [3] arg=4 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 NOT IN (a,1.0,2.0,3.0,NULL) FROM t1;
+1 NOT IN (a,1.0,2.0,3.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=0 (decimal)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: [3] arg=4 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10));
+SELECT 'a' IN (a,'b','c') FROM t1;
+'a' IN (a,'b','c')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 'a' IN (a,'b','c',NULL) FROM t1;
+'a' IN (a,'b','c',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 'a' NOT IN (a,'b','c') FROM t1;
+'a' NOT IN (a,'b','c')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 'a' NOT IN (a,'b','c',NULL) FROM t1;
+'a' NOT IN (a,'b','c',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [2] arg=3 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a DATE);
+SELECT DATE'2001-01-01' IN (a,'2001-01-01') FROM t1;
+DATE'2001-01-01' IN (a,'2001-01-01')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT DATE'2001-01-01' IN (a,'2001-01-01',NULL) FROM t1;
+DATE'2001-01-01' IN (a,'2001-01-01',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT DATE'2001-01-01' NOT IN (a,'2001-01-01') FROM t1;
+DATE'2001-01-01' NOT IN (a,'2001-01-01')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT DATE'2001-01-01' NOT IN (a,'2001-01-01',NULL) FROM t1;
+DATE'2001-01-01' NOT IN (a,'2001-01-01',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (date)
+Note 1105 DBUG: [1] arg=2 handler=0 (date)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a TIME);
+SELECT TIME'10:20:30' IN (a,'10:20:30') FROM t1;
+TIME'10:20:30' IN (a,'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT TIME'10:20:30' IN (a,'10:20:30',NULL) FROM t1;
+TIME'10:20:30' IN (a,'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT TIME'10:20:30' NOT IN (a,'10:20:30') FROM t1;
+TIME'10:20:30' NOT IN (a,'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT TIME'10:20:30' NOT IN (a,'10:20:30',NULL) FROM t1;
+TIME'10:20:30' NOT IN (a,'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a DATETIME);
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
+Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+# Constant predicant, incompatible types, no bisect
+SELECT 1 IN (1,2e0);
+1 IN (1,2e0)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1 IN (1,2e0,NULL);
+1 IN (1,2e0,NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1 NOT IN (1,2e0);
+1 NOT IN (1,2e0)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1 NOT IN (1,2e0,NULL);
+1 NOT IN (1,2e0,NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1.0 IN (1.0,2e0);
+1.0 IN (1.0,2e0)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1.0 IN (1.0,2e0,NULL);
+1.0 IN (1.0,2e0,NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1.0 NOT IN (1.0,2e0);
+1.0 NOT IN (1.0,2e0)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1.0 NOT IN (1.0,2e0,NULL);
+1.0 NOT IN (1.0,2e0,NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1e0 IN (1.0,TIME'10:20:30');
+1e0 IN (1.0,TIME'10:20:30')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1e0 IN (1.0,TIME'10:20:30',NULL);
+1e0 IN (1.0,TIME'10:20:30',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1e0 NOT IN (1.0,TIME'10:20:30');
+1e0 NOT IN (1.0,TIME'10:20:30')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 1e0 NOT IN (1.0,TIME'10:20:30',NULL);
+1e0 NOT IN (1.0,TIME'10:20:30',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 'a' IN ('a',2);
+'a' IN ('a',2)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 'a' IN ('a',2,NULL);
+'a' IN ('a',2,NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 'a' NOT IN ('a',2);
+'a' NOT IN ('a',2)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT 'a' NOT IN ('a',2,NULL);
+'a' NOT IN ('a',2,NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' IN (1,TIME'10:20:30');
+TIME'10:20:30' IN (1,TIME'10:20:30')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL);
+TIME'10:20:30' IN (1,TIME'10:20:30',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30');
+TIME'10:20:30' NOT IN (1,TIME'10:20:30')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL);
+TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+# Column predicant, incompatible types, no bisect
+CREATE TABLE t1 (a INT);
+SELECT a IN (1,1e0) FROM t1;
+a IN (1,1e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,1e0,NULL) FROM t1;
+a IN (1,1e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,1e0) FROM t1;
+a NOT IN (1,1e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,1e0,NULL) FROM t1;
+a NOT IN (1,1e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (bigint)
+Note 1105 DBUG: [2] arg=3 handler=0 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,1.0) FROM t1;
+a IN (1,1.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,1.0,NULL) FROM t1;
+a IN (1,1.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,1.0) FROM t1;
+a NOT IN (1,1.0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,1.0,NULL) FROM t1;
+a NOT IN (1,1.0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,'1') FROM t1;
+a IN (1,'1')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,'1',NULL) FROM t1;
+a IN (1,'1',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,'1') FROM t1;
+a NOT IN (1,'1')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,'1',NULL) FROM t1;
+a NOT IN (1,'1',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIME'10:20:30') FROM t1;
+a IN (1,TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIME'10:20:30',NULL) FROM t1;
+a IN (1,TIME'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIME'10:20:30') FROM t1;
+a NOT IN (1,TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIME'10:20:30',NULL) FROM t1;
+a NOT IN (1,TIME'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a DECIMAL(10,0));
+SELECT a IN (1,1e0) FROM t1;
+a IN (1,1e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,1e0,NULL) FROM t1;
+a IN (1,1e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,1e0) FROM t1;
+a NOT IN (1,1e0)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,1e0,NULL) FROM t1;
+a NOT IN (1,1e0,NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,'1') FROM t1;
+a IN (1,'1')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,'1',NULL) FROM t1;
+a IN (1,'1',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,'1') FROM t1;
+a NOT IN (1,'1')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,'1',NULL) FROM t1;
+a NOT IN (1,'1',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIME'10:20:30') FROM t1;
+a IN (1,TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIME'10:20:30',NULL) FROM t1;
+a IN (1,TIME'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIME'10:20:30') FROM t1;
+a NOT IN (1,TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIME'10:20:30',NULL) FROM t1;
+a NOT IN (1,TIME'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (decimal)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a DOUBLE);
+SELECT a IN (1,TIME'10:20:30') FROM t1;
+a IN (1,TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIME'10:20:30',NULL) FROM t1;
+a IN (1,TIME'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIME'10:20:30') FROM t1;
+a NOT IN (1,TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIME'10:20:30',NULL) FROM t1;
+a NOT IN (1,TIME'10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,DATE'2001-01-01') FROM t1;
+a IN (1,DATE'2001-01-01')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (date)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,DATE'2001-01-01',NULL) FROM t1;
+a IN (1,DATE'2001-01-01',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (date)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,DATE'2001-01-01') FROM t1;
+a NOT IN (1,DATE'2001-01-01')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (date)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,DATE'2001-01-01',NULL) FROM t1;
+a NOT IN (1,DATE'2001-01-01',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (date)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+a IN (1,TIMESTAMP'2001-01-01 10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (1,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+a IN (1,TIMESTAMP'2001-01-01 10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+a NOT IN (1,TIMESTAMP'2001-01-01 10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (1,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+a NOT IN (1,TIMESTAMP'2001-01-01 10:20:30',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (double)
+Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(10));
+SELECT a IN ('a',1) FROM t1;
+a IN ('a',1)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN ('a',TIME'10:20:30') FROM t1;
+a IN ('a',TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN ('a',1) FROM t1;
+a NOT IN ('a',1)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN ('a',TIME'10:20:30') FROM t1;
+a NOT IN ('a',TIME'10:20:30')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=1 (time)
+Note 1105 DBUG: types_compatible=no bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a TIME);
+SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32')
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL)
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=0 (time)
+Note 1105 DBUG: [3] arg=4 handler=3 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+DROP TABLE t1;
+# Not top level, negated: cond3 is false
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,a) NOT IN ((1,1),(2,NULL)) FROM t1;
+ROW(a,a) NOT IN ((1,1),(2,NULL))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,a) NOT IN ((1,1),(2,2)) FROM t1;
+ROW(a,a) NOT IN ((1,1),(2,2))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL, b INT);
+SELECT ROW(a,a) NOT IN ((1,1),(2,NULL)) FROM t1;
+ROW(a,a) NOT IN ((1,1),(2,NULL))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,a) NOT IN ((1,1),(2,2)) FROM t1;
+ROW(a,a) NOT IN ((1,1),(2,2))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2))) FROM t1;
+ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2))) FROM t1;
+ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+# Not top level, not negated: cond3 is false
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,a) IN ((1,1),(2,NULL)) FROM t1;
+ROW(a,a) IN ((1,1),(2,NULL))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,a) IN ((1,1),(2,2)) FROM t1;
+ROW(a,a) IN ((1,1),(2,2))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT ROW(a,a) IN ((1,1),(2,NULL)) FROM t1;
+ROW(a,a) IN ((1,1),(2,NULL))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,a) IN ((1,1),(2,2)) FROM t1;
+ROW(a,a) IN ((1,1),(2,2))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2))) FROM t1;
+ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2))) FROM t1;
+ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)))
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+# Top level, negated: cond3 is false
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,NULL));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,2));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,NULL));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,2));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+# Top level, not negated: cond3 is true
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,NULL));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,2));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,NULL));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,2));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)));
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (row)
+Note 1105 DBUG: [1] arg=2 handler=0 (row)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+#
+# MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
+#
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+PREPARE stmt FROM "SELECT
+ TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+EXECUTE stmt;
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+EXECUTE stmt;
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
+Note 1105 DBUG: types_compatible=no bisect=no
+DEALLOCATE PREPARE stmt;
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('A'),('B'),('A');
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A');
+a b
+A NULL
+B NULL
+Warnings:
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN ('A',b);
+a b
+A NULL
+B NULL
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,a);
+a b
+A NULL
+Warnings:
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b);
+a b
+A NULL
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A',10);
+a b
+A NULL
+B NULL
+Warnings:
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN ('A',b,10);
+a b
+A NULL
+B NULL
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,a,10);
+a b
+A NULL
+Warnings:
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+Warning 1292 Truncated incorrect DOUBLE value: 'A'
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b,10);
+a b
+A NULL
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
+Warning 1292 Truncated incorrect DOUBLE value: 'A'
+DROP TABLE t1;
+#
+# MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
+#
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT * FROM t1 WHERE -1 IN (a,b);
+a b
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+Note 1105 DBUG: types_compatible=no bisect=no
+DROP TABLE t1;
+#
+# MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
+#
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT
+CASE -1
+WHEN -9223372036854775808 THEN 'one'
+ WHEN 18446744073709551615 THEN 'two'
+ END AS c;
+c
+NULL
+Warnings:
+Note 1105 DBUG: [0] arg=0 handler=0 (bigint)
+Note 1105 DBUG: [1] arg=2 handler=1 (decimal)
+DROP TABLE t1;
+#
+# MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
+#
+SELECT
+CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ END AS good,
+CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
+ END AS was_bad_now_good;
+good was_bad_now_good
+one one
+Warnings:
+Note 1105 DBUG: [0] arg=0 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [0] arg=0 handler=0 (time)
+Note 1105 DBUG: [1] arg=2 handler=0 (time)
+Note 1105 DBUG: [2] arg=4 handler=2 (datetime)
+SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
+SET SESSION debug_dbug="-d,Item_func_in";
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 0c3d649a6bb..097e07ac715 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -996,7 +996,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED td ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select distinct group_concat(`test`.`td`.`f1` separator ',') AS `GROUP_CONCAT(td.f1)` from `test`.`t1` join `test`.`t1` `td` group by `test`.`td`.`f1`) `d` join `test`.`t1`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select distinct group_concat(`test`.`td`.`f1` separator ',') AS `GROUP_CONCAT(td.f1)` from `test`.`t1` join `test`.`t1` `td` group by `test`.`td`.`f1`) `d` join `test`.`t1`
SELECT 1 FROM
(SELECT DISTINCT GROUP_CONCAT(td.f1) FROM t1,t1 AS td GROUP BY td.f1) AS d,t1;
1
@@ -1017,7 +1017,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select 1 AS `1` from (select group_concat(`test`.`t1`.`a` order by `test`.`t1`.`a` ASC separator ',') AS `GROUP_CONCAT(t1.a ORDER BY t1.a ASC)` from `test`.`t1` `t2` join `test`.`t1` group by `test`.`t1`.`a`) `d`
+Note 1003 /* select#1 */ select 1 AS `1` from (/* select#2 */ select group_concat(`test`.`t1`.`a` order by `test`.`t1`.`a` ASC separator ',') AS `GROUP_CONCAT(t1.a ORDER BY t1.a ASC)` from `test`.`t1` `t2` join `test`.`t1` group by `test`.`t1`.`a`) `d`
DROP TABLE t1;
End of 5.0 tests
#
@@ -1044,7 +1044,7 @@ DROP TABLE t1;
CREATE TABLE t1(f1 int);
INSERT INTO t1 values (0),(0);
SELECT POLYGON((SELECT 1 FROM (SELECT 1 IN (GROUP_CONCAT(t1.f1)) FROM t1, t1 t GROUP BY t.f1 ) d));
-ERROR 22007: Illegal non geometric '(select 1 from (select 1 = group_concat(`test`.`t1`.`f1` separator ',') AS `1 IN (GROUP_CONCAT(t1.f1))` from `test`.`t1` join `test`.`t1` `t` group by `test`.`t`.`f1`) `d`)' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
DROP TABLE t1;
#
# Bug#58396 group_concat and explain extended are still crashy
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index c4e991e8cbe..3340328cad6 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -1849,7 +1849,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select max(`test`.`t1`.`a`) AS `MAX(a)` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select max(`test`.`t1`.`a`) AS `MAX(a)` from `test`.`t1` where 0
SELECT MAX(a) FROM t1 WHERE (1,2) IN (SELECT 3,4) AND a<10;
MAX(a)
NULL
@@ -1891,7 +1891,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 100.00
Warnings:
Note 1276 Field or reference 'test.t3.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t3`.`b`>((select min(1) from dual where 10 = `test`.`t3`.`b`)) AS `(SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b)` from `test`.`t3`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t3`.`b`>((/* select#2 */ select min(1) from dual where 10 = `test`.`t3`.`b`)) AS `(SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b)` from `test`.`t3`
SELECT (SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b) FROM t3;
(SELECT MIN(t1.a) FROM t1,t2 WHERE t2.a = t3.b)
NULL
@@ -2398,7 +2398,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t10.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t10`.`a` AS `a` from `test`.`t10` where `test`.`t10`.`c` < 3 or <expr_cache><`test`.`t10`.`a`,`test`.`t10`.`b`>(<in_optimizer>(`test`.`t10`.`a`,<exists>(select `test`.`t12`.`c` from `test`.`t12` where <cache>(`test`.`t10`.`a`) = `test`.`t12`.`c` union select max(`test`.`t10`.`b`) from `test`.`t11` group by `test`.`t11`.`c` having <cache>(`test`.`t10`.`a`) = <ref_null_helper>(max(`test`.`t10`.`b`)))))
+Note 1003 /* select#1 */ select `test`.`t10`.`a` AS `a` from `test`.`t10` where `test`.`t10`.`c` < 3 or <expr_cache><`test`.`t10`.`a`,`test`.`t10`.`b`>(<in_optimizer>(`test`.`t10`.`a`,<exists>(/* select#2 */ select `test`.`t12`.`c` from `test`.`t12` where <cache>(`test`.`t10`.`a`) = `test`.`t12`.`c` union /* select#3 */ select max(`test`.`t10`.`b`) from `test`.`t11` group by `test`.`t11`.`c` having <cache>(`test`.`t10`.`a`) = <ref_null_helper>(max(`test`.`t10`.`b`)))))
drop table t10,t11,t12;
#
# MDEV-10017: Get unexpected `Empty Set` for correlated subquery
@@ -2429,7 +2429,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY tt system NULL NULL NULL NULL 1 100.00
Warnings:
Note 1276 Field or reference 'test.t1.c1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` having `test`.`t1`.`c1` >= <expr_cache><`test`.`t1`.`c1`>((select 2 AS `c` from dual order by (select min(`test`.`t1`.`c1` + 2) from dual)))
+Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` having `test`.`t1`.`c1` >= <expr_cache><`test`.`t1`.`c1`>((/* select#2 */ select 2 AS `c` from dual order by (/* select#3 */ select min(`test`.`t1`.`c1` + 2) from dual)))
select c1 from t1 having c1 >= (select t.c1 as c from t2 t order by (select min(t1.c1+tt.c1) from t2 tt));
c1
2
@@ -2456,3 +2456,36 @@ select count(*)+sleep(0) from t1;
count(*)+sleep(0)
2
drop table t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-9408 CREATE TABLE SELECT MAX(int_column) creates different columns for table vs view
+#
+CREATE TABLE t1 (
+id int(11) NOT NULL PRIMARY KEY,
+country varchar(32),
+code int(11) default NULL
+);
+INSERT INTO t1 VALUES (1,'ITALY',100),(2,'ITALY',200),(3,'FRANCE',100), (4,'ITALY',100);
+CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE TABLE t2 AS SELECT code, COUNT(DISTINCT country), MAX(id) FROM t1 GROUP BY code ORDER BY MAX(id);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `code` int(11) DEFAULT NULL,
+ `COUNT(DISTINCT country)` bigint(21) NOT NULL,
+ `MAX(id)` int(11)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT code, COUNT(DISTINCT country), MAX(id) FROM v1 GROUP BY code ORDER BY MAX(id);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `code` int(11) DEFAULT NULL,
+ `COUNT(DISTINCT country)` bigint(21) NOT NULL,
+ `MAX(id)` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/r/func_hybrid_type.result b/mysql-test/r/func_hybrid_type.result
index 324db452f9b..fe45338b36f 100644
--- a/mysql-test/r/func_hybrid_type.result
+++ b/mysql-test/r/func_hybrid_type.result
@@ -1000,14 +1000,14 @@ t2 CREATE TABLE `t2` (
`least____a_a` int(11) DEFAULT NULL,
`greatest_a_a` int(11) DEFAULT NULL,
`___________b` bit(8) DEFAULT NULL,
- `case_______b` int(8) unsigned DEFAULT NULL,
- `case_____b_b` int(8) unsigned DEFAULT NULL,
- `coalesce___b` int(8) unsigned DEFAULT NULL,
- `coalesce_b_b` int(8) unsigned DEFAULT NULL,
- `if_______b_b` int(8) unsigned DEFAULT NULL,
+ `case_______b` bit(8) DEFAULT NULL,
+ `case_____b_b` bit(8) DEFAULT NULL,
+ `coalesce___b` bit(8) DEFAULT NULL,
+ `coalesce_b_b` bit(8) DEFAULT NULL,
+ `if_______b_b` bit(8) DEFAULT NULL,
`ifnull___b_b` bit(8) DEFAULT NULL,
- `least____b_b` int(8) unsigned DEFAULT NULL,
- `greatest_b_b` int(8) unsigned DEFAULT NULL
+ `least____b_b` bit(8) DEFAULT NULL,
+ `greatest_b_b` bit(8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
@@ -1119,18 +1119,18 @@ GREATEST(a, b) AS greatest_a_b,
GREATEST(b, a) AS greatest_b_a
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def case_____a_b 8 10 10 Y 32928 0 63
-def case_____b_a 8 10 2 Y 32928 0 63
-def coalesce_a_b 8 10 10 Y 32928 0 63
-def coalesce_b_a 8 10 2 Y 32928 0 63
-def if_______a_b 8 10 2 Y 32928 0 63
-def if_______b_a 8 10 10 Y 32928 0 63
-def ifnull___a_b 8 10 10 Y 32928 0 63
-def ifnull___b_a 8 10 2 Y 32928 0 63
-def least____a_b 8 10 2 Y 32928 0 63
-def least____b_a 8 10 2 Y 32928 0 63
-def greatest_a_b 8 10 10 Y 32928 0 63
-def greatest_b_a 8 10 10 Y 32928 0 63
+def case_____a_b 3 10 10 Y 32928 0 63
+def case_____b_a 3 10 2 Y 32928 0 63
+def coalesce_a_b 3 10 10 Y 32928 0 63
+def coalesce_b_a 3 10 2 Y 32928 0 63
+def if_______a_b 3 10 2 Y 32928 0 63
+def if_______b_a 3 10 10 Y 32928 0 63
+def ifnull___a_b 3 10 10 Y 32928 0 63
+def ifnull___b_a 3 10 2 Y 32928 0 63
+def least____a_b 3 10 2 Y 32928 0 63
+def least____b_a 3 10 2 Y 32928 0 63
+def greatest_a_b 3 10 10 Y 32928 0 63
+def greatest_b_a 3 10 10 Y 32928 0 63
case_____a_b 4294967295
case_____b_a 50
coalesce_a_b 4294967295
@@ -1177,14 +1177,14 @@ t2 CREATE TABLE `t2` (
`least____a_a` int(10) unsigned DEFAULT NULL,
`greatest_a_a` int(10) unsigned DEFAULT NULL,
`___________b` bit(8) DEFAULT NULL,
- `case_______b` int(8) unsigned DEFAULT NULL,
- `case_____b_b` int(8) unsigned DEFAULT NULL,
- `coalesce___b` int(8) unsigned DEFAULT NULL,
- `coalesce_b_b` int(8) unsigned DEFAULT NULL,
- `if_______b_b` int(8) unsigned DEFAULT NULL,
+ `case_______b` bit(8) DEFAULT NULL,
+ `case_____b_b` bit(8) DEFAULT NULL,
+ `coalesce___b` bit(8) DEFAULT NULL,
+ `coalesce_b_b` bit(8) DEFAULT NULL,
+ `if_______b_b` bit(8) DEFAULT NULL,
`ifnull___b_b` bit(8) DEFAULT NULL,
- `least____b_b` int(8) unsigned DEFAULT NULL,
- `greatest_b_b` int(8) unsigned DEFAULT NULL
+ `least____b_b` bit(8) DEFAULT NULL,
+ `greatest_b_b` bit(8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
@@ -1212,8 +1212,8 @@ t2 CREATE TABLE `t2` (
`coalesce_b_a` int(10) unsigned DEFAULT NULL,
`if_______a_b` int(10) unsigned DEFAULT NULL,
`if_______b_a` int(10) unsigned DEFAULT NULL,
- `ifnull___a_b` bigint(10) unsigned DEFAULT NULL,
- `ifnull___b_a` bigint(10) unsigned DEFAULT NULL,
+ `ifnull___a_b` int(10) unsigned DEFAULT NULL,
+ `ifnull___b_a` int(10) unsigned DEFAULT NULL,
`least____a_b` int(10) unsigned DEFAULT NULL,
`least____b_a` int(10) unsigned DEFAULT NULL,
`greatest_a_b` int(10) unsigned DEFAULT NULL,
@@ -1345,23 +1345,23 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`___________a` bit(7) DEFAULT NULL,
- `case_______a` int(7) unsigned DEFAULT NULL,
- `case_____a_a` int(7) unsigned DEFAULT NULL,
- `coalesce___a` int(7) unsigned DEFAULT NULL,
- `coalesce_a_a` int(7) unsigned DEFAULT NULL,
- `if_______a_a` int(7) unsigned DEFAULT NULL,
+ `case_______a` bit(7) DEFAULT NULL,
+ `case_____a_a` bit(7) DEFAULT NULL,
+ `coalesce___a` bit(7) DEFAULT NULL,
+ `coalesce_a_a` bit(7) DEFAULT NULL,
+ `if_______a_a` bit(7) DEFAULT NULL,
`ifnull___a_a` bit(7) DEFAULT NULL,
- `least____a_a` int(7) unsigned DEFAULT NULL,
- `greatest_a_a` int(7) unsigned DEFAULT NULL,
+ `least____a_a` bit(7) DEFAULT NULL,
+ `greatest_a_a` bit(7) DEFAULT NULL,
`___________b` bit(8) DEFAULT NULL,
- `case_______b` int(8) unsigned DEFAULT NULL,
- `case_____b_b` int(8) unsigned DEFAULT NULL,
- `coalesce___b` int(8) unsigned DEFAULT NULL,
- `coalesce_b_b` int(8) unsigned DEFAULT NULL,
- `if_______b_b` int(8) unsigned DEFAULT NULL,
+ `case_______b` bit(8) DEFAULT NULL,
+ `case_____b_b` bit(8) DEFAULT NULL,
+ `coalesce___b` bit(8) DEFAULT NULL,
+ `coalesce_b_b` bit(8) DEFAULT NULL,
+ `if_______b_b` bit(8) DEFAULT NULL,
`ifnull___b_b` bit(8) DEFAULT NULL,
- `least____b_b` int(8) unsigned DEFAULT NULL,
- `greatest_b_b` int(8) unsigned DEFAULT NULL
+ `least____b_b` bit(8) DEFAULT NULL,
+ `greatest_b_b` bit(8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
@@ -1383,18 +1383,18 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `case_____a_b` int(8) unsigned DEFAULT NULL,
- `case_____b_a` int(8) unsigned DEFAULT NULL,
- `coalesce_a_b` int(8) unsigned DEFAULT NULL,
- `coalesce_b_a` int(8) unsigned DEFAULT NULL,
- `if_______a_b` int(8) unsigned DEFAULT NULL,
- `if_______b_a` int(8) unsigned DEFAULT NULL,
+ `case_____a_b` bit(8) DEFAULT NULL,
+ `case_____b_a` bit(8) DEFAULT NULL,
+ `coalesce_a_b` bit(8) DEFAULT NULL,
+ `coalesce_b_a` bit(8) DEFAULT NULL,
+ `if_______a_b` bit(8) DEFAULT NULL,
+ `if_______b_a` bit(8) DEFAULT NULL,
`ifnull___a_b` bit(8) DEFAULT NULL,
`ifnull___b_a` bit(8) DEFAULT NULL,
- `least____a_b` int(8) unsigned DEFAULT NULL,
- `least____b_a` int(8) unsigned DEFAULT NULL,
- `greatest_a_b` int(8) unsigned DEFAULT NULL,
- `greatest_b_a` int(8) unsigned DEFAULT NULL
+ `least____a_b` bit(8) DEFAULT NULL,
+ `least____b_a` bit(8) DEFAULT NULL,
+ `greatest_a_b` bit(8) DEFAULT NULL,
+ `greatest_b_a` bit(8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
@@ -1429,8 +1429,8 @@ def coalesce___a 4 12 1 Y 32896 31 63
def coalesce_a_a 4 12 1 Y 32896 31 63
def if_______a_a 4 12 1 Y 32896 31 63
def ifnull___a_a 4 12 1 Y 32896 31 63
-def least____a_a 5 23 1 Y 32896 31 63
-def greatest_a_a 5 23 1 Y 32896 31 63
+def least____a_a 4 23 1 Y 32896 31 63
+def greatest_a_a 4 23 1 Y 32896 31 63
def test t1 t1 b ___________b 2 6 6 Y 32768 0 63
def case_______b 2 6 6 Y 32896 0 63
def case_____b_b 2 6 6 Y 32896 0 63
@@ -1522,23 +1522,23 @@ SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`___________a` float DEFAULT NULL,
- `case_______a` double DEFAULT NULL,
- `case_____a_a` double DEFAULT NULL,
- `coalesce___a` double DEFAULT NULL,
- `coalesce_a_a` double DEFAULT NULL,
- `if_______a_a` double DEFAULT NULL,
+ `case_______a` float DEFAULT NULL,
+ `case_____a_a` float DEFAULT NULL,
+ `coalesce___a` float DEFAULT NULL,
+ `coalesce_a_a` float DEFAULT NULL,
+ `if_______a_a` float DEFAULT NULL,
`ifnull___a_a` float DEFAULT NULL,
- `least____a_a` double DEFAULT NULL,
- `greatest_a_a` double DEFAULT NULL,
+ `least____a_a` float DEFAULT NULL,
+ `greatest_a_a` float DEFAULT NULL,
`___________b` smallint(6) DEFAULT NULL,
- `case_______b` int(6) DEFAULT NULL,
- `case_____b_b` int(6) DEFAULT NULL,
- `coalesce___b` int(6) DEFAULT NULL,
- `coalesce_b_b` int(6) DEFAULT NULL,
- `if_______b_b` int(6) DEFAULT NULL,
+ `case_______b` smallint(6) DEFAULT NULL,
+ `case_____b_b` smallint(6) DEFAULT NULL,
+ `coalesce___b` smallint(6) DEFAULT NULL,
+ `coalesce_b_b` smallint(6) DEFAULT NULL,
+ `if_______b_b` smallint(6) DEFAULT NULL,
`ifnull___b_b` smallint(6) DEFAULT NULL,
- `least____b_b` int(6) DEFAULT NULL,
- `greatest_b_b` int(6) DEFAULT NULL
+ `least____b_b` smallint(6) DEFAULT NULL,
+ `greatest_b_b` smallint(6) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
@@ -1560,12 +1560,12 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `case_____a_b` double DEFAULT NULL,
- `case_____b_a` double DEFAULT NULL,
- `coalesce_a_b` double DEFAULT NULL,
- `coalesce_b_a` double DEFAULT NULL,
- `if_______a_b` double DEFAULT NULL,
- `if_______b_a` double DEFAULT NULL,
+ `case_____a_b` float DEFAULT NULL,
+ `case_____b_a` float DEFAULT NULL,
+ `coalesce_a_b` float DEFAULT NULL,
+ `coalesce_b_a` float DEFAULT NULL,
+ `if_______a_b` float DEFAULT NULL,
+ `if_______b_a` float DEFAULT NULL,
`ifnull___a_b` float DEFAULT NULL,
`ifnull___b_a` float DEFAULT NULL,
`least____a_b` double DEFAULT NULL,
@@ -1615,8 +1615,8 @@ def coalesce___b 254 1 1 Y 0 39 8
def coalesce_b_b 254 1 1 Y 0 39 8
def if_______b_b 254 1 1 Y 0 39 8
def ifnull___b_b 254 1 1 Y 0 39 8
-def least____b_b 254 1 1 Y 0 0 8
-def greatest_b_b 254 1 1 Y 0 0 8
+def least____b_b 254 1 1 Y 0 39 8
+def greatest_b_b 254 1 1 Y 0 39 8
___________a a
case_______a a
case_____a_a a
@@ -1885,14 +1885,14 @@ t2 CREATE TABLE `t2` (
`least____a_a` int(11) DEFAULT NULL,
`greatest_a_a` int(11) DEFAULT NULL,
`___________b` year(4) DEFAULT NULL,
- `case_______b` int(4) unsigned DEFAULT NULL,
- `case_____b_b` int(4) unsigned DEFAULT NULL,
- `coalesce___b` int(4) unsigned DEFAULT NULL,
- `coalesce_b_b` int(4) unsigned DEFAULT NULL,
- `if_______b_b` int(4) unsigned DEFAULT NULL,
+ `case_______b` year(4) DEFAULT NULL,
+ `case_____b_b` year(4) DEFAULT NULL,
+ `coalesce___b` year(4) DEFAULT NULL,
+ `coalesce_b_b` year(4) DEFAULT NULL,
+ `if_______b_b` year(4) DEFAULT NULL,
`ifnull___b_b` year(4) DEFAULT NULL,
- `least____b_b` int(4) unsigned DEFAULT NULL,
- `greatest_b_b` int(4) unsigned DEFAULT NULL
+ `least____b_b` year(4) DEFAULT NULL,
+ `greatest_b_b` year(4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
@@ -2062,14 +2062,14 @@ t2 CREATE TABLE `t2` (
`least____a_a` int(10) unsigned DEFAULT NULL,
`greatest_a_a` int(10) unsigned DEFAULT NULL,
`___________b` year(4) DEFAULT NULL,
- `case_______b` int(4) unsigned DEFAULT NULL,
- `case_____b_b` int(4) unsigned DEFAULT NULL,
- `coalesce___b` int(4) unsigned DEFAULT NULL,
- `coalesce_b_b` int(4) unsigned DEFAULT NULL,
- `if_______b_b` int(4) unsigned DEFAULT NULL,
+ `case_______b` year(4) DEFAULT NULL,
+ `case_____b_b` year(4) DEFAULT NULL,
+ `coalesce___b` year(4) DEFAULT NULL,
+ `coalesce_b_b` year(4) DEFAULT NULL,
+ `if_______b_b` year(4) DEFAULT NULL,
`ifnull___b_b` year(4) DEFAULT NULL,
- `least____b_b` int(4) unsigned DEFAULT NULL,
- `greatest_b_b` int(4) unsigned DEFAULT NULL
+ `least____b_b` year(4) DEFAULT NULL,
+ `greatest_b_b` year(4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
@@ -2190,10 +2190,10 @@ def if_______a_b 12 19 19 Y 128 0 63
def if_______b_a 12 19 19 Y 128 0 63
def ifnull___a_b 12 19 19 Y 128 0 63
def ifnull___b_a 12 19 19 Y 128 0 63
-def least____a_b 12 10 19 Y 128 0 63
-def least____b_a 12 10 19 Y 128 0 63
-def greatest_a_b 12 10 19 Y 128 0 63
-def greatest_b_a 12 10 19 Y 128 0 63
+def least____a_b 12 19 19 Y 128 0 63
+def least____b_a 12 19 19 Y 128 0 63
+def greatest_a_b 12 19 19 Y 128 0 63
+def greatest_b_a 12 19 19 Y 128 0 63
case_____a_b 2010-01-01 00:00:00
case_____b_a 2001-01-01 10:20:30
coalesce_a_b 2010-01-01 00:00:00
@@ -2317,8 +2317,8 @@ def coalesce___a 7 19 19 N 129 0 63
def coalesce_a_a 7 19 19 N 129 0 63
def if_______a_a 7 19 19 N 129 0 63
def ifnull___a_a 7 19 19 N 129 0 63
-def least____a_a 7 19 19 N 161 0 63
-def greatest_a_a 7 19 19 N 161 0 63
+def least____a_a 7 19 19 N 129 0 63
+def greatest_a_a 7 19 19 N 129 0 63
def test t1 t1 b ___________b 11 10 8 Y 128 0 63
def case_______b 11 10 8 Y 128 0 63
def case_____b_b 11 10 8 Y 128 0 63
@@ -3050,7 +3050,7 @@ DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2010-01-01 01:02:03');
SELECT GREATEST(CURRENT_TIME, CURRENT_DATE), COALESCE(CURRENT_TIME, CURRENT_DATE);
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def GREATEST(CURRENT_TIME, CURRENT_DATE) 12 10 19 N 129 0 63
+def GREATEST(CURRENT_TIME, CURRENT_DATE) 12 19 19 N 129 0 63
def COALESCE(CURRENT_TIME, CURRENT_DATE) 12 19 19 N 129 0 63
GREATEST(CURRENT_TIME, CURRENT_DATE) COALESCE(CURRENT_TIME, CURRENT_DATE)
2010-01-01 01:02:03 2010-01-01 01:02:03
@@ -3058,9 +3058,14 @@ CREATE TABLE t1 (a TIMESTAMP);
INSERT INTO t1 VALUES ('2010-01-01 10:20:30');
SELECT GREATEST(a,a) FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def GREATEST(a,a) 7 19 19 N 161 0 63
+def GREATEST(a,a) 7 19 19 N 129 0 63
GREATEST(a,a)
2010-01-01 10:20:30
+SELECT COALESCE(a,a) FROM t1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def COALESCE(a,a) 7 19 19 N 129 0 63
+COALESCE(a,a)
+2010-01-01 10:20:30
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP, b DATETIME);
CREATE TABLE t2 AS SELECT LEAST(a,a),LEAST(b,b),LEAST(a,b) FROM t1;
@@ -3445,3 +3450,308 @@ DROP TABLE t1;
#
# End of 10.1 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12497 Wrong data type for LEAST(latin1_expr, utf8_expr)
+#
+CREATE TABLE t1 AS SELECT
+LEAST(_latin1'aaa',_utf8 0xC39F) AS c1,
+COALESCE(_latin1'aaa',_utf8 0xC39F) AS c2;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(3) CHARACTER SET utf8 NOT NULL,
+ `c2` varchar(3) CHARACTER SET utf8 NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+aaa aaa
+DROP TABLE t1;
+#
+# MDEV-12504 Wrong data type for LEAST(date_expr,time_expr)
+#
+CREATE TABLE t1 AS SELECT
+LEAST(DATE'2001-01-01', TIME'10:20:30') AS c1,
+CONCAT(LEAST(DATE'2001-01-01', TIME'10:20:30')) AS c2;
+SELECT * FROM t1;
+c1 c2
+2001-01-01 00:00:00 2001-01-01 00:00:00
+DROP TABLE t1;
+#
+# MDEV-12505 Wrong data type for GREATEST(bit_column, int_column)
+#
+CREATE TABLE t1 (a BIT(64),b INT);
+INSERT INTO t1 VALUES (0xFFFFFFFFFFFFFFFF,-1);
+SELECT a>b, COALESCE(a,b), GREATEST(a,b) FROM t1;
+a>b COALESCE(a,b) GREATEST(a,b)
+1 18446744073709551615 18446744073709551615
+CREATE TABLE t2 AS SELECT COALESCE(a,b),GREATEST(a,b) FROM t1;
+SELECT * FROM t2;
+COALESCE(a,b) GREATEST(a,b)
+18446744073709551615 18446744073709551615
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` decimal(64,0) DEFAULT NULL,
+ `GREATEST(a,b)` decimal(64,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-12601 Hybrid functions create a column of an impossible type DOUBLE(256,4)
+#
+CREATE TABLE t1 (a DOUBLE(255,4),b DOUBLE(255,3));
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` double(255,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-12617 CASE and CASE-alike hybrid functions do not preserve exact data types
+#
+CREATE TABLE t1 (a FLOAT(10,2));
+CREATE TABLE t2 AS SELECT COALESCE(a) FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a)` float(10,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2, t1;
+CREATE TABLE t1 (a FLOAT(10,2));
+CREATE TABLE t2 AS SELECT LEAST(a,a) FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,a)` float(19,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2, t1;
+CREATE TABLE t1 (a TINYINT(1));
+CREATE TABLE t2 AS SELECT COALESCE(a) FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a)` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2, t1;
+CREATE TABLE t1 (a TINYINT(1));
+CREATE TABLE t2 AS SELECT LEAST(a,a) FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,a)` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2, t1;
+#
+# MDEV-12875 Wrong VIEW column data type for COALESCE(int_column)
+#
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE VIEW v1 AS SELECT COALESCE(a) FROM t1;
+DESCRIBE v1;
+Field Type Null Key Default Extra
+COALESCE(a) int(11) YES NULL
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# MDEV-10309 COALESCE(12345678900) makes a column of a wrong type and truncates the data
+#
+CREATE TABLE t1 AS SELECT 12345678900 AS c1, COALESCE(12345678900) AS c2;
+SELECT * FROM t1;
+c1 c2
+12345678900 12345678900
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` bigint(11) NOT NULL,
+ `c2` bigint(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT
+9 AS i1, COALESCE(9) AS c1,
+99 AS i2, COALESCE(99) AS c2,
+999 AS i3, COALESCE(999) AS c3,
+9999 AS i4, COALESCE(9999) AS c4,
+99999 AS i5, COALESCE(99999) AS c5,
+999999 AS i6, COALESCE(999999) AS c6,
+9999999 AS i7, COALESCE(9999999) AS c7,
+99999999 AS i8, COALESCE(99999999) AS c8,
+999999999 AS i9, COALESCE(999999999) AS c9,
+2147483647, COALESCE(2147483647),
+2147483648, COALESCE(2147483648),
+9999999999 AS i10, COALESCE(9999999999) AS c10,
+99999999999 AS i11, COALESCE(99999999999) AS c11,
+999999999999 AS i12, COALESCE(999999999999) AS c12,
+9999999999999 AS i13, COALESCE(9999999999999) AS c13,
+99999999999999 AS i14, COALESCE(99999999999999) AS c14,
+999999999999999 AS i15, COALESCE(999999999999999) AS c15,
+9999999999999999 AS i16, COALESCE(9999999999999999) AS c16,
+99999999999999999 AS i17, COALESCE(99999999999999999) AS c17,
+999999999999999999 AS i18, COALESCE(999999999999999999) AS c18,
+9223372036854775807, COALESCE(9223372036854775807),
+9223372036854775808, COALESCE(9223372036854775808),
+9999999999999999999 AS i19, COALESCE(9999999999999999999) AS c19,
+18446744073709551615, COALESCE(18446744073709551615),
+18446744073709551616, COALESCE(18446744073709551616),
+99999999999999999999 AS i20, COALESCE(99999999999999999999) AS c20,
+999999999999999999999 AS i21, COALESCE(999999999999999999999) AS c21,
+9999999999999999999999 AS i22, COALESCE(9999999999999999999999) AS c22;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i1` int(1) NOT NULL,
+ `c1` int(1) NOT NULL,
+ `i2` int(2) NOT NULL,
+ `c2` int(2) NOT NULL,
+ `i3` int(3) NOT NULL,
+ `c3` int(3) NOT NULL,
+ `i4` int(4) NOT NULL,
+ `c4` int(4) NOT NULL,
+ `i5` int(5) NOT NULL,
+ `c5` int(5) NOT NULL,
+ `i6` int(6) NOT NULL,
+ `c6` int(6) NOT NULL,
+ `i7` int(7) NOT NULL,
+ `c7` int(7) NOT NULL,
+ `i8` int(8) NOT NULL,
+ `c8` int(8) NOT NULL,
+ `i9` int(9) NOT NULL,
+ `c9` int(9) NOT NULL,
+ `2147483647` bigint(10) NOT NULL,
+ `COALESCE(2147483647)` bigint(10) NOT NULL,
+ `2147483648` bigint(10) NOT NULL,
+ `COALESCE(2147483648)` bigint(10) NOT NULL,
+ `i10` bigint(10) NOT NULL,
+ `c10` bigint(10) NOT NULL,
+ `i11` bigint(11) NOT NULL,
+ `c11` bigint(11) NOT NULL,
+ `i12` bigint(12) NOT NULL,
+ `c12` bigint(12) NOT NULL,
+ `i13` bigint(13) NOT NULL,
+ `c13` bigint(13) NOT NULL,
+ `i14` bigint(14) NOT NULL,
+ `c14` bigint(14) NOT NULL,
+ `i15` bigint(15) NOT NULL,
+ `c15` bigint(15) NOT NULL,
+ `i16` bigint(16) NOT NULL,
+ `c16` bigint(16) NOT NULL,
+ `i17` bigint(17) NOT NULL,
+ `c17` bigint(17) NOT NULL,
+ `i18` bigint(18) NOT NULL,
+ `c18` bigint(18) NOT NULL,
+ `9223372036854775807` bigint(19) NOT NULL,
+ `COALESCE(9223372036854775807)` bigint(19) NOT NULL,
+ `9223372036854775808` bigint(19) unsigned NOT NULL,
+ `COALESCE(9223372036854775808)` bigint(19) unsigned NOT NULL,
+ `i19` bigint(19) unsigned NOT NULL,
+ `c19` bigint(19) unsigned NOT NULL,
+ `18446744073709551615` bigint(20) unsigned NOT NULL,
+ `COALESCE(18446744073709551615)` bigint(20) unsigned NOT NULL,
+ `18446744073709551616` decimal(20,0) NOT NULL,
+ `COALESCE(18446744073709551616)` decimal(20,0) NOT NULL,
+ `i20` decimal(20,0) NOT NULL,
+ `c20` decimal(20,0) NOT NULL,
+ `i21` decimal(21,0) NOT NULL,
+ `c21` decimal(21,0) NOT NULL,
+ `i22` decimal(22,0) NOT NULL,
+ `c22` decimal(22,0) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+i1 9
+c1 9
+i2 99
+c2 99
+i3 999
+c3 999
+i4 9999
+c4 9999
+i5 99999
+c5 99999
+i6 999999
+c6 999999
+i7 9999999
+c7 9999999
+i8 99999999
+c8 99999999
+i9 999999999
+c9 999999999
+2147483647 2147483647
+COALESCE(2147483647) 2147483647
+2147483648 2147483648
+COALESCE(2147483648) 2147483648
+i10 9999999999
+c10 9999999999
+i11 99999999999
+c11 99999999999
+i12 999999999999
+c12 999999999999
+i13 9999999999999
+c13 9999999999999
+i14 99999999999999
+c14 99999999999999
+i15 999999999999999
+c15 999999999999999
+i16 9999999999999999
+c16 9999999999999999
+i17 99999999999999999
+c17 99999999999999999
+i18 999999999999999999
+c18 999999999999999999
+9223372036854775807 9223372036854775807
+COALESCE(9223372036854775807) 9223372036854775807
+9223372036854775808 9223372036854775808
+COALESCE(9223372036854775808) 9223372036854775808
+i19 9999999999999999999
+c19 9999999999999999999
+18446744073709551615 18446744073709551615
+COALESCE(18446744073709551615) 18446744073709551615
+18446744073709551616 18446744073709551616
+COALESCE(18446744073709551616) 18446744073709551616
+i20 99999999999999999999
+c20 99999999999999999999
+i21 999999999999999999999
+c21 999999999999999999999
+i22 9999999999999999999999
+c22 9999999999999999999999
+DROP TABLE t1;
+#
+# MDEV-9406 CREATE TABLE..SELECT creates different columns for IFNULL() and equivalent COALESCE,CASE,IF
+#
+CREATE TABLE t1 (a SMALLINT);
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 AS SELECT
+IFNULL(a,a) AS c1,
+COALESCE(a,a) AS c2,
+CASE WHEN a IS NOT NULL THEN a ELSE a END AS c3,
+IF(a IS NULL,a,a) AS c4 FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `c1` smallint(6) DEFAULT NULL,
+ `c2` smallint(6) DEFAULT NULL,
+ `c3` smallint(6) DEFAULT NULL,
+ `c4` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2,t1;
+CREATE TABLE t1 AS SELECT
+connection_id() AS c0,
+IFNULL(connection_id(),connection_id()) AS c1,
+COALESCE(connection_id(), connection_id()) AS c2,
+CASE WHEN 0 THEN connection_id() ELSE connection_id() END AS c3,
+IF(0,connection_id(),connection_id()) AS c4;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c0` int(10) NOT NULL,
+ `c1` int(10) NOT NULL,
+ `c2` int(10) NOT NULL,
+ `c3` int(10) NOT NULL,
+ `c4` int(10) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index d18681bc80d..f12fc40e9aa 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -857,3 +857,34 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` in (1,2,'3')
DROP TABLE t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
+#
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+PREPARE stmt FROM "SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
+EXECUTE stmt;
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+EXECUTE stmt;
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+DEALLOCATE PREPARE stmt;
+#
+# MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
+#
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT * FROM t1 WHERE -1 IN (a,b);
+a b
+PREPARE stmt FROM 'SELECT * FROM t1 WHERE -1 IN (a,b)';
+EXECUTE stmt;
+a b
+EXECUTE stmt;
+a b
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result
index 997d3e4d062..03e4c48a3e1 100644
--- a/mysql-test/r/func_json.result
+++ b/mysql-test/r/func_json.result
@@ -642,3 +642,29 @@ SELECT JSON_KEYS(f) FROM t1 ORDER BY 1;
JSON_KEYS(f)
NULL
DROP TABLE t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+SELECT
+JSON_VALID('{"id": 1, "name": "Monty"}') AS json_valid,
+JSON_EXISTS('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2") AS json_exists,
+JSON_CONTAINS('{"A": 0, "B": {"C": 1}, "D": 2}', '2', '$.A') AS ison_contains,
+JSON_CONTAINS_PATH('{"A": 1, "B": [2], "C": [3, 4]}', 'one', '$.A', '$.D') AS json_contains_path;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def json_valid 3 1 1 Y 32896 0 63
+def json_exists 3 1 1 Y 32896 0 63
+def ison_contains 3 1 1 Y 32896 0 63
+def json_contains_path 3 1 1 Y 32896 0 63
+json_valid json_exists ison_contains json_contains_path
+1 1 0 1
+SELECT
+JSON_LENGTH('{"a": 1, "b": {"c": 30}}') AS json_length,
+JSON_DEPTH('[10, {"a": 20}]') AS json_depnth;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def json_length 3 10 1 Y 32896 0 63
+def json_depnth 3 10 1 N 32897 0 63
+json_length json_depnth
+2 3
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index 8ca10203add..c99d7e62285 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -566,9 +566,9 @@ DROP TABLE t1;
# Bug#11764994 57900: CREATE TABLE .. SELECT ASSERTS SCALE >= 0 && PRECISION > 0 && SCALE <= PR
#
CREATE TABLE t1 SELECT CEIL(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
#
# Bug#11765923 58937: MANY VALGRIND ERRORS AFTER GROUPING BY RESULT OF DECIMAL COLUMN FUNCTION
#
@@ -838,3 +838,60 @@ select 0=0, 0=-0, 0.0= -0.0, 0.0 = -(0.0), 0.0E1=-0.0E1, 0.0E1=-(0.0E1);
select CRC32(NULL), CRC32(''), CRC32('MySQL'), CRC32('mysql'), CRC32('01234567'), CRC32('012345678');
CRC32(NULL) CRC32('') CRC32('MySQL') CRC32('mysql') CRC32('01234567') CRC32('012345678')
NULL 0 3259397556 2501908538 763378421 939184570
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12000 ROUND(expr,const_expr_returning_NULL) creates DOUBLE(0,0)
+#
+CREATE OR REPLACE TABLE t1 AS SELECT
+ROUND(10,NULL) AS c1,
+ROUND(10.1,NULL) AS c2,
+ROUND(10e0,NULL) AS c3;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` double DEFAULT NULL,
+ `c2` double DEFAULT NULL,
+ `c3` double DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# MDEV-12857 Out-of-range errors on CREATE..SELECT 2222222222 DIV 1
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE OR REPLACE TABLE t1 AS SELECT
+2 DIV 1 AS d01,
+222222222 DIV 1 AS d09,
+2222222222 DIV 1 AS d10;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `d01` int(1) DEFAULT NULL,
+ `d09` int(9) DEFAULT NULL,
+ `d10` bigint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+d01 2
+d09 222222222
+d10 2222222222
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# MDEV-12858 Out-of-range error for CREATE..SELECT unsigned_int_column+1
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE OR REPLACE TABLE t1 (a INT UNSIGNED NOT NULL);
+INSERT INTO t1 VALUES (0xFFFFFFFF);
+CREATE OR REPLACE TABLE t2 AS SELECT a+1 AS a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` bigint(11) unsigned NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT a, HEX(a) FROM t2;
+a HEX(a)
+4294967296 100000000
+DROP TABLE t2;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index bbc7f1a0a0a..39f8f41d1e7 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -354,7 +354,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tv ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY tv system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` left join (`test`.`tv`) on(`test`.`tv`.`e` = `test`.`t1`.`a`) where !<expr_cache><last_value(NULL,`test`.`tv`.`e`)>(<in_optimizer>(last_value(NULL,`test`.`tv`.`e`),<exists>(select last_value(NULL,'1') from dual where trigcond(<cache>(last_value(NULL,`test`.`tv`.`e`)) = last_value(NULL,'1')))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` left join (`test`.`tv`) on(`test`.`tv`.`e` = `test`.`t1`.`a`) where !<expr_cache><last_value(NULL,`test`.`tv`.`e`)>(<in_optimizer>(last_value(NULL,`test`.`tv`.`e`),<exists>(/* select#2 */ select last_value(NULL,'1') from dual where trigcond(<cache>(last_value(NULL,`test`.`tv`.`e`)) = last_value(NULL,'1')))))
explain extended
select a from t1 left join v_merge on (a=e) where e not in (select last_value(NULL,e) from vm);
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -362,7 +362,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tv ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (flat, BNL join)
2 DEPENDENT SUBQUERY tv system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` left join (`test`.`tv`) on(`test`.`tv`.`e` = `test`.`t1`.`a`) where !<expr_cache><`test`.`tv`.`e`>(<in_optimizer>(`test`.`tv`.`e`,<exists>(select last_value(NULL,'1') from dual where trigcond(<cache>(`test`.`tv`.`e`) = last_value(NULL,'1')))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` left join (`test`.`tv`) on(`test`.`tv`.`e` = `test`.`t1`.`a`) where !<expr_cache><`test`.`tv`.`e`>(<in_optimizer>(`test`.`tv`.`e`,<exists>(/* select#2 */ select last_value(NULL,'1') from dual where trigcond(<cache>(`test`.`tv`.`e`) = last_value(NULL,'1')))))
set optimizer_switch=@optimizer_switch_save;
drop view v_merge, vm;
drop table t1,tv;
@@ -1494,3 +1494,14 @@ DROP TABLE t1;
#
# End of 10.2 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+SELECT INET_ATON("255.255.255.255.255.255.255.255");
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def INET_ATON("255.255.255.255.255.255.255.255") 8 21 20 Y 32928 0 63
+INET_ATON("255.255.255.255.255.255.255.255")
+18446744073709551615
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 8ca0d8c0297..464178124ec 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -297,6 +297,9 @@ STRINGpadpadpadpadpa
select lpad('STRING', 20, CONCAT('p','a','d') );
lpad('STRING', 20, CONCAT('p','a','d') )
padpadpadpadpaSTRING
+select rpad('abcd',7),lpad('abcd',7);
+rpad('abcd',7) lpad('abcd',7)
+abcd abcd
select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD');
LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD') GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD')
NULL NULL
@@ -637,9 +640,15 @@ latin2_general_ci 4
select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b'));
collation(lpad(_latin2'a',4,_latin2'b')) coercibility(lpad(_latin2'a',4,_latin2'b'))
latin2_general_ci 4
+select collation(lpad(_latin2'a',4)), coercibility(lpad(_latin2'a',4));
+collation(lpad(_latin2'a',4)) coercibility(lpad(_latin2'a',4))
+latin2_general_ci 4
select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b'));
collation(rpad(_latin2'a',4,_latin2'b')) coercibility(rpad(_latin2'a',4,_latin2'b'))
latin2_general_ci 4
+select collation(rpad(_latin2'a',4)), coercibility(rpad(_latin2'a',4));
+collation(rpad(_latin2'a',4)) coercibility(rpad(_latin2'a',4))
+latin2_general_ci 4
select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b'));
collation(concat_ws(_latin2'a',_latin2'b')) coercibility(concat_ws(_latin2'a',_latin2'b'))
latin2_general_ci 4
@@ -707,6 +716,8 @@ substring(_latin2'a',1,1),
concat(_latin2'a',_latin2'b'),
lpad(_latin2'a',4,_latin2'b'),
rpad(_latin2'a',4,_latin2'b'),
+lpad(_latin2'a',4),
+rpad(_latin2'a',4),
concat_ws(_latin2'a',_latin2'b'),
make_set(255,_latin2'a',_latin2'b',_latin2'c'),
export_set(255,_latin2'y',_latin2'n',_latin2' '),
@@ -742,6 +753,8 @@ t1 CREATE TABLE `t1` (
`concat(_latin2'a',_latin2'b')` varchar(2) CHARACTER SET latin2 DEFAULT NULL,
`lpad(_latin2'a',4,_latin2'b')` varchar(4) CHARACTER SET latin2 DEFAULT NULL,
`rpad(_latin2'a',4,_latin2'b')` varchar(4) CHARACTER SET latin2 DEFAULT NULL,
+ `lpad(_latin2'a',4)` varchar(4) CHARACTER SET latin2 DEFAULT NULL,
+ `rpad(_latin2'a',4)` varchar(4) CHARACTER SET latin2 DEFAULT NULL,
`concat_ws(_latin2'a',_latin2'b')` varchar(1) CHARACTER SET latin2 DEFAULT NULL,
`make_set(255,_latin2'a',_latin2'b',_latin2'c')` varchar(5) CHARACTER SET latin2 DEFAULT NULL,
`export_set(255,_latin2'y',_latin2'n',_latin2' ')` varchar(127) CHARACTER SET latin2 DEFAULT NULL,
@@ -869,6 +882,16 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select lpad('a',4,'1') AS `lpad('a',4,'1')`
+explain extended select rpad('a',4);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select rpad('a',4) AS `rpad('a',4)`
+explain extended select lpad('a',4);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select lpad('a',4) AS `lpad('a',4)`
explain extended select concat_ws(',','',NULL,'a');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
@@ -943,7 +966,7 @@ explain extended select length('\n\t\r\b\0\_\%\\');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select length('\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`
+Note 1003 select octet_length('\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`
explain extended select bit_length('\n\t\r\b\0\_\%\\');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
@@ -963,7 +986,7 @@ explain extended select length('hello');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select length('hello') AS `length('hello')`
+Note 1003 select octet_length('hello') AS `length('hello')`
explain extended select char(ascii('h'));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
@@ -1402,7 +1425,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 const PRIMARY PRIMARY 12 const 1 100.00 Using index
1 SIMPLE t1 ref code code 13 const 3 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1`.`code` AS `code`,'a12' AS `id` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`code` = 'a12' and length(`test`.`t1`.`code`) = 5
+Note 1003 select `test`.`t1`.`code` AS `code`,'a12' AS `id` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`code` = 'a12' and octet_length(`test`.`t1`.`code`) = 5
DROP TABLE t1,t2;
select encode(NULL, NULL);
encode(NULL, NULL)
@@ -2213,6 +2236,76 @@ Warnings:
Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -1);
+rpad('hello', -1)
+NULL
+select rpad('hello', -4294967295);
+rpad('hello', -4294967295)
+NULL
+select rpad('hello', 4294967295);
+rpad('hello', 4294967295)
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -4294967296);
+rpad('hello', -4294967296)
+NULL
+select rpad('hello', 4294967296);
+rpad('hello', 4294967296)
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -4294967297);
+rpad('hello', -4294967297)
+NULL
+select rpad('hello', 4294967297);
+rpad('hello', 4294967297)
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -18446744073709551615);
+rpad('hello', -18446744073709551615)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '-18446744073709551615' to INT. Value truncated
+Warning 1916 Got overflow when converting '-18446744073709551615' to INT. Value truncated
+select rpad('hello', 18446744073709551615);
+rpad('hello', 18446744073709551615)
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -18446744073709551616);
+rpad('hello', -18446744073709551616)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '-18446744073709551616' to INT. Value truncated
+Warning 1916 Got overflow when converting '-18446744073709551616' to INT. Value truncated
+select rpad('hello', 18446744073709551616);
+rpad('hello', 18446744073709551616)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated
+Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -18446744073709551617);
+rpad('hello', -18446744073709551617)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '-18446744073709551617' to INT. Value truncated
+Warning 1916 Got overflow when converting '-18446744073709551617' to INT. Value truncated
+select rpad('hello', 18446744073709551617);
+rpad('hello', 18446744073709551617)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
+Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', 0, 'x');
+rpad('hello', 0, 'x')
+
+select rpad('hello', 0);
+rpad('hello', 0)
+
select lpad('hello', -1, '1');
lpad('hello', -1, '1')
NULL
@@ -2277,6 +2370,85 @@ Warnings:
Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -1);
+lpad('hello', -1)
+NULL
+select lpad('hello', -4294967295);
+lpad('hello', -4294967295)
+NULL
+select lpad('hello', 4294967295);
+lpad('hello', 4294967295)
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -4294967296);
+lpad('hello', -4294967296)
+NULL
+select lpad('hello', 4294967296);
+lpad('hello', 4294967296)
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -4294967297);
+lpad('hello', -4294967297)
+NULL
+select lpad('hello', 4294967297);
+lpad('hello', 4294967297)
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -18446744073709551615);
+lpad('hello', -18446744073709551615)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '-18446744073709551615' to INT. Value truncated
+Warning 1916 Got overflow when converting '-18446744073709551615' to INT. Value truncated
+select lpad('hello', 18446744073709551615);
+lpad('hello', 18446744073709551615)
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -18446744073709551616);
+lpad('hello', -18446744073709551616)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '-18446744073709551616' to INT. Value truncated
+Warning 1916 Got overflow when converting '-18446744073709551616' to INT. Value truncated
+select lpad('hello', 18446744073709551616);
+lpad('hello', 18446744073709551616)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated
+Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -18446744073709551617);
+lpad('hello', -18446744073709551617)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '-18446744073709551617' to INT. Value truncated
+Warning 1916 Got overflow when converting '-18446744073709551617' to INT. Value truncated
+select lpad('hello', 18446744073709551617);
+lpad('hello', 18446744073709551617)
+NULL
+Warnings:
+Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
+Warning 1916 Got overflow when converting '18446744073709551617' to INT. Value truncated
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', 0, 'x');
+lpad('hello', 0, 'x')
+
+select lpad('hello', 0);
+lpad('hello', 0)
+
+Check parameters count rpad / lpad
+select rpad('x');
+ERROR 42000: Incorrect parameter count in the call to native function 'rpad'
+select rpad('x',2,'.','z');
+ERROR 42000: Incorrect parameter count in the call to native function 'rpad'
+select lpad('x');
+ERROR 42000: Incorrect parameter count in the call to native function 'lpad'
+select lpad('x',2,'.','z');
+ERROR 42000: Incorrect parameter count in the call to native function 'lpad'
SET @orig_sql_mode = @@SQL_MODE;
SET SQL_MODE=traditional;
SELECT CHAR(0xff,0x8f USING utf8);
@@ -2302,6 +2474,12 @@ abcxx
select lpad('abc', cast(5 as unsigned integer), 'x');
lpad('abc', cast(5 as unsigned integer), 'x')
xxabc
+select rpad('abc', cast(5 as unsigned integer));
+rpad('abc', cast(5 as unsigned integer))
+abc
+select lpad('abc', cast(5 as unsigned integer));
+lpad('abc', cast(5 as unsigned integer))
+ abc
create table t1(f1 longtext);
insert into t1 values ("123"),("456");
select substring(f1,1,1) from t1 group by 1;
@@ -2663,6 +2841,12 @@ NULL
SELECT LPAD('hi', DAY(FROM_UNIXTIME(-1)),'?');
LPAD('hi', DAY(FROM_UNIXTIME(-1)),'?')
NULL
+SELECT RPAD('hi', DAY(FROM_UNIXTIME(-1)));
+RPAD('hi', DAY(FROM_UNIXTIME(-1)))
+NULL
+SELECT LPAD('hi', DAY(FROM_UNIXTIME(-1)));
+LPAD('hi', DAY(FROM_UNIXTIME(-1)))
+NULL
create table t1 (i int);
insert into t1 values (null),(8);
select group_concat( i ), make_set( i, 'a', 'b' ) field from t1 group by field;
@@ -2940,13 +3124,7 @@ sha1('P'),
)
)
) AS r;
-r
-0
-Warnings:
-Warning 1292 Truncated incorrect INTEGER value: '511993d3c99719e38a6779073019dacd7178ddb9'
-Warning 1292 Truncated incorrect DECIMAL value: '[.DC2.]'
-Warning 1292 Truncated incorrect INTEGER value: '511993d3c99719e38a6779073019dacd7178ddb9'
-Warning 1292 Truncated incorrect DOUBLE value: '0.000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'
+ERROR HY000: Illegal parameter data type varchar for operation 'st_geometryfromwkb'
connection conn1;
SET @@global.max_allowed_packet:= @tmp_max;
disconnect newconn;
@@ -4665,5 +4843,49 @@ YQ== 61
Yq== 62
DROP TABLE t1;
#
+# MDEV-12685 Oracle-compatible function CHR()
+#
+select chr(65);
+chr(65)
+A
+create database mysqltest1 CHARACTER SET = 'utf8' COLLATE = 'utf8_bin';
+use mysqltest1;
+select charset(chr(65)), length(chr(65)),char_length(chr(65));
+charset(chr(65)) length(chr(65)) char_length(chr(65))
+utf8 1 1
+select charset(chr(14844588)), length(chr(14844588)),char_length(chr(14844588));
+charset(chr(14844588)) length(chr(14844588)) char_length(chr(14844588))
+utf8 3 1
+drop database mysqltest1;
+use test;
+#
# End of 10.1 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12592 Illegal mix of collations with the HEX function
+#
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES (0x09),('a');
+SELECT IF(a<' ',HEX(a),a) FROM t1 ORDER BY a;
+IF(a<' ',HEX(a),a)
+09
+a
+DROP TABLE t1;
+#
+# MDEV-12783 sql_mode=ORACLE: Functions LENGTH() and LENGTHB()
+#
+SELECT LENGTHB('a'), LENGTHB(_utf8 0xC39F), LENGTHB(123), LENGTH(null);
+LENGTHB('a') LENGTHB(_utf8 0xC39F) LENGTHB(123) LENGTH(null)
+1 2 3 NULL
+EXPLAIN EXTENDED SELECT LENGTH('a'), LENGTHB('a');
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select octet_length('a') AS `LENGTH('a')`,octet_length('a') AS `LENGTHB('a')`
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 54da823c439..fb0179026c9 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -950,10 +950,10 @@ sec_to_time(1) + 0, from_unixtime(1) + 0;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `now() - now()` bigint(21) NOT NULL,
- `curtime() - curtime()` bigint(12) NOT NULL,
- `sec_to_time(1) + 0` bigint(12) DEFAULT NULL,
- `from_unixtime(1) + 0` bigint(21) DEFAULT NULL
+ `now() - now()` bigint(16) NOT NULL,
+ `curtime() - curtime()` int(9) NOT NULL,
+ `sec_to_time(1) + 0` int(9) DEFAULT NULL,
+ `from_unixtime(1) + 0` bigint(16) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
SELECT SEC_TO_TIME(3300000);
@@ -2054,11 +2054,11 @@ SEC_TO_TIME(1.123456)+0.1,
SEC_TO_TIME(1.1234567)+0.1;
SHOW COLUMNS FROM t1;
Field Type Null Key Default Extra
-SEC_TO_TIME(1)+0.1 decimal(12,1) YES NULL
-SEC_TO_TIME(1.1)+0.1 decimal(13,1) YES NULL
-SEC_TO_TIME(1.12)+0.1 decimal(14,2) YES NULL
-SEC_TO_TIME(1.123456)+0.1 decimal(18,6) YES NULL
-SEC_TO_TIME(1.1234567)+0.1 decimal(18,6) YES NULL
+SEC_TO_TIME(1)+0.1 decimal(9,1) YES NULL
+SEC_TO_TIME(1.1)+0.1 decimal(9,1) YES NULL
+SEC_TO_TIME(1.12)+0.1 decimal(10,2) YES NULL
+SEC_TO_TIME(1.123456)+0.1 decimal(14,6) YES NULL
+SEC_TO_TIME(1.1234567)+0.1 decimal(14,6) YES NULL
DROP TABLE t1;
CREATE TABLE t1 (a DATE) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('2005-05-04'),('2000-02-23');
@@ -3210,3 +3210,87 @@ DROP TABLE t1,t2;
#
# End of 10.1 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12515 Wrong value when storing DATE_ADD() and ADDTIME() to a numeric field
+#
+SET sql_mode='';
+CREATE TABLE t1 AS SELECT
+DATE_ADD('2001-01-01',INTERVAL 1 DAY) AS c1,
+ADDTIME('10:20:30',1) AS c2;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(19) DEFAULT NULL,
+ `c2` varchar(26) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1 c2
+2001-01-02 10:20:31
+DROP TABLE t1;
+CREATE TABLE t2 (c INT);
+INSERT INTO t2 SELECT DATE_ADD('2001-01-01',INTERVAL 1 DAY);
+Warnings:
+Warning 1265 Data truncated for column 'c' at row 1
+INSERT INTO t2 VALUES ('2001-01-02');
+Warnings:
+Warning 1265 Data truncated for column 'c' at row 1
+SELECT * FROM t2;
+c
+2001
+2001
+DROP TABLE t2;
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (ADDTIME('10:20:30',1));
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+INSERT INTO t2 VALUES ('10:20:31');
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+SELECT * FROM t2;
+a
+10
+10
+DROP TABLE t2;
+SET sql_mode=DEFAULT;
+#
+# MDEV-12860 Out-of-range error on CREATE..SELECT with a view using MAX and EXTRACT(MINUTE_MICROSECOND..)
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 (
+id bigint(11) NOT NULL PRIMARY KEY,
+dt datetime(6)
+);
+INSERT INTO t1 VALUES (1,'2001-01-01 11:22:33.123456');
+CREATE OR REPLACE VIEW v1 AS SELECT EXTRACT(MINUTE_MICROSECOND FROM dt) AS dt2 FROM t1;
+DESCRIBE v1;
+Field Type Null Key Default Extra
+dt2 bigint(11) YES NULL
+SELECT * FROM v1;
+dt2
+2233123456
+CREATE TABLE t2 AS SELECT MAX(dt2) FROM v1;
+DESCRIBE t2;
+Field Type Null Key Default Extra
+MAX(dt2) bigint(11) YES NULL
+SELECT * FROM t2;
+MAX(dt2)
+2233123456
+DROP TABLE t2;
+DROP VIEW v1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# MDEV-12866 Out-of-range error with CREATE..SELECT..TO_SECONDS(NOW())
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT TO_SECONDS('9999-12-31 23:59:59');
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `TO_SECONDS('9999-12-31 23:59:59')` bigint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/r/func_weight_string.result b/mysql-test/r/func_weight_string.result
index 04fd9962218..5fa78c861a9 100644
--- a/mysql-test/r/func_weight_string.result
+++ b/mysql-test/r/func_weight_string.result
@@ -57,7 +57,7 @@ create table t1 select weight_string(repeat('t',66000)) as w;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `w` longblob DEFAULT NULL
+ `w` mediumblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select weight_string(NULL);
diff --git a/mysql-test/r/get_diagnostics.result b/mysql-test/r/get_diagnostics.result
index fbe3a02ee88..abd2fdd4da9 100644
--- a/mysql-test/r/get_diagnostics.result
+++ b/mysql-test/r/get_diagnostics.result
@@ -587,6 +587,10 @@ DROP PROCEDURE p1;
# The same statement information item can be used multiple times.
+SHOW WARNINGS;
+Level Code Message
+Error 54321 MESSAGE_TEXT text
+Note 4070 At line 16 in test.p1
CREATE PROCEDURE p1()
BEGIN
DECLARE var INT;
@@ -595,7 +599,7 @@ SELECT var, @var;
END|
CALL p1();
var @var
-1 1
+2 2
DROP PROCEDURE p1;
# Setting TABLE_NAME is currently not implemented.
diff --git a/mysql-test/r/gis-debug.result b/mysql-test/r/gis-debug.result
index 79adef34b98..1516c3d5089 100644
--- a/mysql-test/r/gis-debug.result
+++ b/mysql-test/r/gis-debug.result
@@ -305,3 +305,103 @@ ERROR HY000: Function or expression 'st_gis_debug()' cannot be used in the DEFAU
#
# End of 10.2 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# Comparison data type aggregation for pluggable data types
+#
+SET SESSION debug_dbug="+d,Item_func_in";
+SET SESSION debug_dbug="+d,Predicant_to_list_comparator";
+CREATE TABLE t1 (a POINT);
+INSERT INTO t1 VALUES (POINT(1,1)),(POINT(1,2)),(POINT(1,3));
+SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30));
+COUNT(*)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (geometry)
+Note 1105 DBUG: [1] arg=2 handler=0 (geometry)
+Note 1105 DBUG: [2] arg=3 handler=0 (geometry)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30),'test');
+COUNT(*)
+1
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (geometry)
+Note 1105 DBUG: [1] arg=2 handler=0 (geometry)
+Note 1105 DBUG: [2] arg=3 handler=0 (geometry)
+Note 1105 DBUG: [3] arg=4 handler=3 (longblob)
+Note 1105 DBUG: types_compatible=no bisect=no
+SELECT COUNT(*) FROM t1 WHERE a IN ('test','test1');
+COUNT(*)
+0
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+CREATE TABLE t1 (a TEXT);
+INSERT INTO t1 VALUES ('test'),('test1'),('test2');
+SELECT * FROM t1 WHERE a IN ('test',POINT(1,1));
+a
+test
+Warnings:
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=yes
+DROP TABLE t1;
+SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
+SET SESSION debug_dbug="-d,Item_func_in";
+#
+# MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
+#
+SET debug_dbug='+d,num_op';
+CREATE TABLE t1 AS SELECT
+POINT(0,0)+POINT(0,0),
+POINT(0,0)-POINT(0,0),
+POINT(0,0)*POINT(0,0),
+POINT(0,0)/POINT(0,0),
+POINT(0,0) MOD POINT(0,0) LIMIT 0;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `POINT(0,0)+POINT(0,0)` geometry DEFAULT NULL,
+ `POINT(0,0)-POINT(0,0)` geometry DEFAULT NULL,
+ `POINT(0,0)*POINT(0,0)` geometry DEFAULT NULL,
+ `POINT(0,0)/POINT(0,0)` geometry DEFAULT NULL,
+ `POINT(0,0) MOD POINT(0,0)` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT
+POINT(0,0)+'0',
+POINT(0,0)-'0',
+POINT(0,0)*'0',
+POINT(0,0)/'0',
+POINT(0,0) MOD '0' LIMIT 0;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `POINT(0,0)+'0'` tinytext DEFAULT NULL,
+ `POINT(0,0)-'0'` tinytext DEFAULT NULL,
+ `POINT(0,0)*'0'` tinytext DEFAULT NULL,
+ `POINT(0,0)/'0'` tinytext DEFAULT NULL,
+ `POINT(0,0) MOD '0'` tinytext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT
+'0'+POINT(0,0),
+'0'*POINT(0,0) LIMIT 0;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `'0'+POINT(0,0)` tinytext DEFAULT NULL,
+ `'0'*POINT(0,0)` tinytext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0;
+ERROR HY000: Illegal parameter data types varchar and geometry for operation '-'
+CREATE TABLE t1 AS SELECT '0'/POINT(0,0) LIMIT 0;
+ERROR HY000: Illegal parameter data types varchar and geometry for operation '/'
+CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0;
+ERROR HY000: Illegal parameter data types varchar and geometry for operation '%'
+SET debug_dbug='-d,num_op';
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result
index 3824ba6afbb..f816278a0ba 100644
--- a/mysql-test/r/gis-precise.result
+++ b/mysql-test/r/gis-precise.result
@@ -223,8 +223,7 @@ st_u
MULTIPOLYGON(((525400 18370,525000.9677614468 183300,525400 183300,525400 18370)),((525000 183300,525000 183700,525000.9677614468 183300,525000 183300)),((525265.58 183481.95,525263.95 183484.75,525260.7 183491.55,525276.79 183500,525278.39 183500.84,525278.63 183500.97,525280.98 183502.26,525283.17 183503.47,525289.11 183506.62,525296.42 183510.31,525296.57 183510.39,525298.67 183511.53,525302.81 183513.8,525304.5 183510.83,525307.85 183504.95,525304.45 183504.25,525301.75 183509.35,525283.55 183500,525282.2 183499.3,525282.3 183499.1,525280.35 183498.2,525275.5 183495.7,525276.5 183493.45,525278.97 183488.73,525265.58 183481.95),(525266.99 183484.33,525263.26 183491.55,525266.15 183493.04,525269.88 183485.82,525266.99 183484.33),(525272.06 183488.37,525268.94 183494.51,525271.94 183496.03,525275.06 183489.89,525272.06 183488.37)))
SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
SELECT ASTEXT(TOUCHES(@a, GEOMFROMTEXT('point(0 0)'))) t;
-t
-NULL
+ERROR HY000: Illegal parameter data type int for operation 'st_astext'
SELECT astext(ST_UNION (
PolyFromText('POLYGON(( 2 2 ,3 2,2 7,2 2),( 0 0,8 2,1 9,0 0))'),
ExteriorRing( Envelope( MultiLineStringFromText('MULTILINESTRING((3 4,5 3),(3 0,0 5))')))));
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index 9373237f1d6..55f7ab8d0bc 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -309,403 +309,403 @@ fid AsText(g)
56 LINESTRING(41 41,50 50)
45 LINESTRING(51 51,60 60)
55 LINESTRING(41 51,50 60)
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
-DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10))));
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), 0)));
SELECT count(*) FROM t2;
count(*)
100
@@ -1617,23 +1617,17 @@ DROP TABLE t1;
CREATE TABLE t1 (a GEOMETRY NOT NULL, SPATIAL KEY(a)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (Point(1,1)),(Point(2,2)),(Point(3,3));
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1);
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type int for operation 'st_contains'
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1.0);
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type decimal for operation 'st_contains'
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1e0);
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type double for operation 'st_contains'
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIME'00:00:00');
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type time for operation 'st_contains'
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,DATE'2001-01-01');
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type date for operation 'st_contains'
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIMESTAMP'2001-01-01 00:00:00');
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+ERROR HY000: Illegal parameter data type datetime for operation 'st_contains'
DROP TABLE t1;
#
# End of 10.1 tests
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 49618c5c8a6..73ec9d3049d 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -709,7 +709,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g
select asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def asbinary(g) 252 4294967295 0 Y 128 0 63
+def asbinary(g) 251 4294967295 0 Y 128 0 63
asbinary(g)
drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
@@ -888,8 +888,8 @@ down3,left3,right3,up3
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
equals
center
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-intersect
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+intersects
big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
overlaps
@@ -1017,7 +1017,7 @@ GEOMFROMTEXT(
'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))'));
# must not crash
SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
-1
+ERROR HY000: Illegal parameter data types int and geometry for operation '<>'
DROP TABLE t1;
#
# Bug #49250 : spatial btree index corruption and crash
@@ -1045,9 +1045,9 @@ f5 datetime YES NULL
drop view v1;
drop table t1;
SELECT MultiPoint(12345,'');
-ERROR 22007: Illegal non geometric '12345' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
-ERROR 22007: Illegal non geometric ''00000'' value found during parsing
+ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
#
# BUG#51875: crash when loading data into geometry function polyfromwkb
#
@@ -1115,7 +1115,7 @@ ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20)))
# GEOMETRY FUNCTION ARGUMENTS
#
SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
-ERROR 22007: Illegal non geometric '' value found during parsing
+ERROR HY000: Illegal parameter data type bigint for operation 'geometrycollection'
#
# MDEV-4252 geometry query crashes server
#
@@ -1614,13 +1614,7 @@ insert into t1 values(geomfromtext("POINT(0 0)"));
insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
select equals(`a`,convert(`a` using utf8)) from `t1`;
-equals(`a`,convert(`a` using utf8))
-1
-NULL
-NULL
-Warnings:
-Warning 1300 Invalid utf8 character string: '\xE0C'
-Warning 1300 Invalid utf8 character string: '\xE0C'
+ERROR HY000: Illegal parameter data type longblob for operation 'st_equals'
select equals(`a`,left(`a`,23)) from `t1`;
equals(`a`,left(`a`,23))
NULL
@@ -1645,11 +1639,7 @@ FLUSH TABLES;
SELECT 1 FROM g1
FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
;
-1
-Warnings:
-Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xF0?'
-Warning 1441 Datetime function: datetime field overflow
-Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\x00@'
+ERROR HY000: Illegal parameter data types geometry and datetime for operation '='
DROP TABLE g1;
#
# Bug#13013970 MORE CRASHES IN FIELD_BLOB::GET_KEY_IMAGE
@@ -2229,5 +2219,2454 @@ c
1
DROP TABLE t1;
#
-# End of 10.2 tests
+# Start of 10.3 tests
+#
+#
+# MDEV-11478 Result data type aggregation for pluggable data types
+#
+CREATE PROCEDURE p2(query TEXT)
+BEGIN
+DECLARE errcount INT DEFAULT 0;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SET errcount = errcount+1;
+#SHOW WARNINGS;
+GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
+SELECT @p AS `ERROR: `;
+END;
+SELECT query AS ``;
+EXECUTE IMMEDIATE query;
+IF errcount = 0
+THEN
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END IF;
+END;
+$$
+CREATE PROCEDURE p1(query TEXT)
+BEGIN
+SELECT query AS `-------------------------------------`;
+EXECUTE IMMEDIATE query;
+CALL p2('CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1');
+CALL p2('CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1');
+CALL p2('CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1');
+CALL p2('CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1');
+CALL p2('CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1');
+DROP TABLE t1;
+END;
+$$
+-------------------------------------
+CREATE TABLE t1 (a CHAR(10), b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a VARCHAR(10), b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a TINYTEXT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a TEXT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a MEDIUMTEXT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a LONGTEXT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a TINYINT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a SMALLINT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a MEDIUMINT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a INT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a BIGINT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a FLOAT, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a DOUBLE, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a DECIMAL(10,2), b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a BIT(8), b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a TIME, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a DATE, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a DATETIME, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a TIMESTAMP, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a YEAR, b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'case'
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'coalesce'
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'if'
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'ifnull'
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'UNION'
+# This creates BLOB with hybrid functions, but fails on error with UNION (MDEV-11458)
+-------------------------------------
+CREATE TABLE t1 (a ENUM(0x61), b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types enum and geometry for operation 'UNION'
+-------------------------------------
+CREATE TABLE t1 (a SET(0x61), b Point)
+
+CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `CASE WHEN TRUE THEN a ELSE b END` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IF(TRUE,a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `IFNULL(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
+ERROR:
+Illegal parameter data types set and geometry for operation 'UNION'
+CREATE TABLE t1 AS SELECT COALESCE(NULL, Point(1,1));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `COALESCE(NULL, Point(1,1))` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT NULL UNION SELECT Point(1,1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `NULL` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# MDEV-11692 Comparison data type aggregation for pluggable data types
+#
+CREATE PROCEDURE p2(query TEXT)
+BEGIN
+DECLARE errcount INT DEFAULT 0;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SET errcount = errcount+1;
+GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
+SELECT @p AS `ERROR: `;
+END;
+SELECT query AS ``;
+EXECUTE IMMEDIATE query;
+END;
+$$
+CREATE PROCEDURE p1(query TEXT)
+BEGIN
+SELECT query AS `-------------------------------------`;
+EXECUTE IMMEDIATE query;
+CALL p2('SELECT a=b FROM t1');
+CALL p2('SELECT b=a FROM t1');
+CALL p2('SELECT a BETWEEN b AND c FROM t1');
+CALL p2('SELECT a IN (b,c) FROM t1');
+CALL p2('SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1');
+CALL p2('SELECT a=POINT(1,1) FROM t1');
+CALL p2('SELECT POINT(1,1)=a FROM t1');
+CALL p2('SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1');
+CALL p2('SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1');
+CALL p2('SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1');
+DROP TABLE t1;
+END;
+$$
+CALL p1('CREATE TABLE t1 (a CHAR(10), b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a CHAR(10), b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a VARCHAR(10), b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a TINYTEXT, b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a TEXT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a TEXT, b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a MEDIUMTEXT, b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a LONGTEXT, b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a ENUM("a","b"), b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a ENUM("a","b"), b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+CALL p1('CREATE TABLE t1 (a TINYINT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a TINYINT, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and tinyint for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and tinyint for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a SMALLINT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a SMALLINT, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and smallint for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and smallint for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a MEDIUMINT, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and mediumint for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and mediumint for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a INT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a INT, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and int for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and int for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a BIGINT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a BIGINT, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and bigint for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and bigint for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a FLOAT, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a FLOAT, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and float for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and float for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a DOUBLE, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a DOUBLE, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and double for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and double for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a DECIMAL(10,2), b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and decimal for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and decimal for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a BIT(8), b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a BIT(8), b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and bit for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and bit for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a TIME, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a TIME, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and time for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and time for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a DATE, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a DATE, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and date for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and date for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a DATETIME, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a DATETIME, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and datetime for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and datetime for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a TIMESTAMP, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and timestamp for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and timestamp for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a YEAR, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a YEAR, b Point, c Point)
+
+SELECT a=b FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation '='
+
+SELECT b=a FROM t1
+ERROR:
+Illegal parameter data types geometry and year for operation '='
+
+SELECT a BETWEEN b AND c FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'between'
+
+SELECT a IN (b,c) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'in'
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'case..when'
+
+SELECT a=POINT(1,1) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation '='
+
+SELECT POINT(1,1)=a FROM t1
+ERROR:
+Illegal parameter data types geometry and year for operation '='
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'between'
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'in'
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'case..when'
+CALL p1('CREATE TABLE t1 (a Point, b Point, c Point)');
+-------------------------------------
+CREATE TABLE t1 (a Point, b Point, c Point)
+
+SELECT a=b FROM t1
+a=b
+
+SELECT b=a FROM t1
+b=a
+
+SELECT a BETWEEN b AND c FROM t1
+a BETWEEN b AND c
+
+SELECT a IN (b,c) FROM t1
+a IN (b,c)
+
+SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1
+CASE a WHEN b THEN "a" WHEN c THEN "b" END
+
+SELECT a=POINT(1,1) FROM t1
+a=POINT(1,1)
+
+SELECT POINT(1,1)=a FROM t1
+POINT(1,1)=a
+
+SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1
+a BETWEEN POINT(1,1) AND POINT(1,2)
+
+SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1
+a IN (POINT(1,1),POINT(1,2))
+
+SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1
+CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods in Type_handler
+#
+CREATE PROCEDURE p2(query TEXT)
+BEGIN
+DECLARE errcount INT DEFAULT 0;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+BEGIN
+SET errcount = errcount+1;
+#SHOW WARNINGS;
+GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
+SELECT @p AS `ERROR: `;
+END;
+SELECT query AS ``;
+EXECUTE IMMEDIATE query;
+IF errcount = 0
+THEN
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END IF;
+END;
+$$
+CREATE PROCEDURE p1(query TEXT)
+BEGIN
+SELECT query AS `-------------------------------------`;
+EXECUTE IMMEDIATE query;
+CALL p2('CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1');
+DROP TABLE t1;
+END;
+$$
+-------------------------------------
+CREATE TABLE t1 (a CHAR(10), b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a VARCHAR(10), b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a TINYTEXT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a TEXT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a MEDIUMTEXT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a LONGTEXT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a TINYINT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types tinyint and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a SMALLINT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types smallint and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a MEDIUMINT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types mediumint and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a INT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types int and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a BIGINT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types bigint and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a FLOAT, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types float and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a DOUBLE, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types double and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a DECIMAL(10,2), b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types decimal and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a BIT(8), b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types bit and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a TIME, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types time and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a DATE, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types date and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a DATETIME, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types datetime and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a TIMESTAMP, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types timestamp and geometry for operation 'least'
+-------------------------------------
+CREATE TABLE t1 (a YEAR, b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+ERROR:
+Illegal parameter data types year and geometry for operation 'least'
+# This LEAST(ENUM,GEOMETRY) creates BLOB, but fails on error with UNION (see MDEV-12503)
+-------------------------------------
+CREATE TABLE t1 (a ENUM(0x61), b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+-------------------------------------
+CREATE TABLE t1 (a SET(0x61), b Point)
+
+CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `LEAST(a,b)` longblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CREATE TABLE t1 AS SELECT LEAST(NULL, Point(1,1));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `LEAST(NULL, Point(1,1))` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# MDEV-12001 Split Item_func_round::fix_length_and_dec to virtual methods in Type_handler
+#
+CREATE TABLE t1 (a GEOMETRY);
+SELECT ROUND(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'round'
+DROP TABLE t1;
+SELECT ROUND(POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'round'
+#
+# MDEV-12199 Split Item_func_{abs|neg|int_val}::fix_length_and_dec() into methods in Type_handler
+#
+CREATE TABLE t1 (a GEOMETRY);
+SELECT -a FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation '-'
+SELECT ABS(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'abs'
+SELECT CEILING(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'ceiling'
+SELECT FLOOR(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'floor'
+SELECT -COALESCE(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation '-'
+SELECT ABS(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'abs'
+SELECT CEILING(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'ceiling'
+SELECT FLOOR(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'floor'
+DROP TABLE t1;
+SELECT -POINT(1,1);
+ERROR HY000: Illegal parameter data type geometry for operation '-'
+SELECT ABS(POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'abs'
+SELECT CEILING(POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'ceiling'
+SELECT FLOOR(POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'floor'
+#
+# MDEV-12239 Add Type_handler::Item_sum_{sum|avg|variance}_fix_length_and_dec()
+#
+CREATE TABLE t1 (a GEOMETRY);
+SELECT SUM(POINT(1,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'sum'
+SELECT SUM(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'sum'
+SELECT SUM(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'sum'
+SELECT AVG(POINT(1,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'avg'
+SELECT AVG(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'avg'
+SELECT AVG(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'avg'
+SELECT VARIANCE(POINT(1,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'variance('
+SELECT VARIANCE(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'variance('
+SELECT VARIANCE(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'variance('
+SELECT STDDEV(POINT(1,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'std('
+SELECT STDDEV(a) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'std('
+SELECT STDDEV(COALESCE(a)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'std('
+DROP TABLE t1;
+#
+# MDEV-12303 Add Type_handler::Item_xxx_fix_length_and_dec() for CAST classes
+#
+CREATE TABLE t1 (a GEOMETRY);
+SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
+SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
+SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
+SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'decimal_typecast'
+SELECT CAST(POINT(1,1) AS CHAR) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_char'
+SELECT CAST(POINT(1,1) AS TIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_time'
+SELECT CAST(POINT(1,1) AS DATE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_date'
+SELECT CAST(POINT(1,1) AS DATETIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_datetime'
+SELECT CAST(a AS SIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
+SELECT CAST(a AS UNSIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
+SELECT CAST(a AS DOUBLE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
+SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'decimal_typecast'
+SELECT CAST(a AS CHAR) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_char'
+SELECT CAST(a AS TIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_time'
+SELECT CAST(a AS DATE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_date'
+SELECT CAST(a AS DATETIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_datetime'
+SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
+SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
+SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
+SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'decimal_typecast'
+SELECT CAST(COALESCE(a) AS CHAR) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_char'
+SELECT CAST(COALESCE(a) AS TIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_time'
+SELECT CAST(COALESCE(a) AS DATE) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_date'
+SELECT CAST(COALESCE(a) AS DATETIME) FROM t1;
+ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_datetime'
+SELECT LENGTH(CAST(POINT(1,1) AS BINARY)) FROM t1;
+LENGTH(CAST(POINT(1,1) AS BINARY))
+SELECT LENGTH(CAST(a AS BINARY)) FROM t1;
+LENGTH(CAST(a AS BINARY))
+SELECT LENGTH(CAST(COALESCE(a) AS BINARY)) FROM t1;
+LENGTH(CAST(COALESCE(a) AS BINARY))
+DROP TABLE t1;
+#
+# MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
+#
+CREATE TABLE t1 (a GEOMETRY);
+SELECT POINT(1,1) + 1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '+'
+SELECT POINT(1,1) - 1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '-'
+SELECT POINT(1,1) * 1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '*'
+SELECT POINT(1,1) / 1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '/'
+SELECT POINT(1,1) MOD 1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '%'
+SELECT 1 + POINT(1,1);
+ERROR HY000: Illegal parameter data types int and geometry for operation '+'
+SELECT 1 - POINT(1,1);
+ERROR HY000: Illegal parameter data types int and geometry for operation '-'
+SELECT 1 * POINT(1,1);
+ERROR HY000: Illegal parameter data types int and geometry for operation '*'
+SELECT 1 / POINT(1,1);
+ERROR HY000: Illegal parameter data types int and geometry for operation '/'
+SELECT 1 MOD POINT(1,1);
+ERROR HY000: Illegal parameter data types int and geometry for operation '%'
+SELECT a + 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '+'
+SELECT a - 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '-'
+SELECT a * 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '*'
+SELECT a / 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '/'
+SELECT a MOD 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '%'
+SELECT 1 + a FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '+'
+SELECT 1 - a FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '-'
+SELECT 1 * a FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '*'
+SELECT 1 / a FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '/'
+SELECT 1 MOD a FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '%'
+SELECT COALESCE(a) + 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '+'
+SELECT COALESCE(a) - 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '-'
+SELECT COALESCE(a) * 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '*'
+SELECT COALESCE(a) / 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '/'
+SELECT COALESCE(a) MOD 1 FROM t1;
+ERROR HY000: Illegal parameter data types geometry and int for operation '%'
+SELECT 1 + COALESCE(a) FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '+'
+SELECT 1 - COALESCE(a) FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '-'
+SELECT 1 * COALESCE(a) FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '*'
+SELECT 1 / COALESCE(a) FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '/'
+SELECT 1 MOD COALESCE(a) FROM t1;
+ERROR HY000: Illegal parameter data types int and geometry for operation '%'
+DROP TABLE t1;
+#
+# MDEV-12514 Split Item_temporal_func::fix_length_and_dec()
+#
+SELECT DATE_ADD(POINT(1,1), INTERVAL 10 DAY);
+ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
+SELECT DATE_SUB(POINT(1,1), INTERVAL 10 DAY);
+ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
+SELECT POINT(1,1) + INTERVAL 10 DAY;
+ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
+SELECT POINT(1,1) - INTERVAL 10 DAY;
+ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
+SELECT INTERVAL 10 DAY + POINT(1,1);
+ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
+SELECT INTERVAL 10 DAY + POINT(1,1);
+ERROR HY000: Illegal parameter data types geometry and interval for operation 'date_add_interval'
+SELECT ADDTIME(POINT(1,1), '10:10:10');
+ERROR HY000: Illegal parameter data types geometry and varchar for operation 'add_time'
+SELECT ADDTIME('10:10:10', POINT(1,1));
+ERROR HY000: Illegal parameter data types varchar and geometry for operation 'add_time'
+SELECT ADDTIME(POINT(1,1), TIME'10:10:10');
+ERROR HY000: Illegal parameter data types geometry and time for operation 'add_time'
+SELECT ADDTIME(TIME'10:10:10', POINT(1,1));
+ERROR HY000: Illegal parameter data types time and geometry for operation 'add_time'
+SELECT ADDTIME(POINT(1,1), TIMESTAMP'2001-01-01 10:10:10');
+ERROR HY000: Illegal parameter data types geometry and datetime for operation 'add_time'
+SELECT ADDTIME(TIMESTAMP'2001-01-01 10:10:10', POINT(1,1));
+ERROR HY000: Illegal parameter data types datetime and geometry for operation 'add_time'
+SELECT STR_TO_DATE(POINT(1,1),'%M %d,%Y');
+ERROR HY000: Illegal parameter data types geometry and varchar for operation 'str_to_date'
+SELECT STR_TO_DATE('2001-01-01', POINT(1,1));
+ERROR HY000: Illegal parameter data types varchar and geometry for operation 'str_to_date'
+#
+# MDEV-12665 Hybrid functions do not preserve geometry type
+#
+CREATE TABLE t1 AS SELECT
+Point(0,0) AS p0,
+COALESCE(Point(0,0)) AS p1,
+CASE WHEN 0 THEN Point(0,0) ELSE Point(1,1) END AS p2;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `p0` point DEFAULT NULL,
+ `p1` point DEFAULT NULL,
+ `p2` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT LEAST(Point(0,0),Point(0,0)) AS p1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `p1` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (
+c_geometry GEOMETRY,
+c_point POINT,
+c_linestring LINESTRING,
+c_polygon POLYGON,
+c_multipoint MULTIPOINT,
+c_multilinestring MULTILINESTRING,
+c_multipolygon MULTIPOLYGON,
+c_geometrycollection GEOMETRYCOLLECTION
+);
+CREATE TABLE t2 AS SELECT
+COALESCE(NULL, c_geometry),
+COALESCE(NULL, c_point),
+COALESCE(NULL, c_linestring),
+COALESCE(NULL, c_polygon),
+COALESCE(NULL, c_multipoint),
+COALESCE(NULL, c_multilinestring),
+COALESCE(NULL, c_multipolygon),
+COALESCE(NULL, c_geometrycollection)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(NULL, c_geometry)` geometry DEFAULT NULL,
+ `COALESCE(NULL, c_point)` point DEFAULT NULL,
+ `COALESCE(NULL, c_linestring)` linestring DEFAULT NULL,
+ `COALESCE(NULL, c_polygon)` polygon DEFAULT NULL,
+ `COALESCE(NULL, c_multipoint)` multipoint DEFAULT NULL,
+ `COALESCE(NULL, c_multilinestring)` multilinestring DEFAULT NULL,
+ `COALESCE(NULL, c_multipolygon)` multipolygon DEFAULT NULL,
+ `COALESCE(NULL, c_geometrycollection)` geometrycollection DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+COALESCE(c_geometry, NULL),
+COALESCE(c_point, NULL),
+COALESCE(c_linestring, NULL),
+COALESCE(c_polygon, NULL),
+COALESCE(c_multipoint, NULL),
+COALESCE(c_multilinestring, NULL),
+COALESCE(c_multipolygon, NULL),
+COALESCE(c_geometrycollection, NULL)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(c_geometry, NULL)` geometry DEFAULT NULL,
+ `COALESCE(c_point, NULL)` point DEFAULT NULL,
+ `COALESCE(c_linestring, NULL)` linestring DEFAULT NULL,
+ `COALESCE(c_polygon, NULL)` polygon DEFAULT NULL,
+ `COALESCE(c_multipoint, NULL)` multipoint DEFAULT NULL,
+ `COALESCE(c_multilinestring, NULL)` multilinestring DEFAULT NULL,
+ `COALESCE(c_multipolygon, NULL)` multipolygon DEFAULT NULL,
+ `COALESCE(c_geometrycollection, NULL)` geometrycollection DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+COALESCE(c_geometry, c_geometry),
+COALESCE(c_point, c_point),
+COALESCE(c_linestring, c_linestring),
+COALESCE(c_polygon, c_polygon),
+COALESCE(c_multipoint, c_multipoint),
+COALESCE(c_multilinestring, c_multilinestring),
+COALESCE(c_multipolygon, c_multipolygon),
+COALESCE(c_geometrycollection, c_geometrycollection)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(c_geometry, c_geometry)` geometry DEFAULT NULL,
+ `COALESCE(c_point, c_point)` point DEFAULT NULL,
+ `COALESCE(c_linestring, c_linestring)` linestring DEFAULT NULL,
+ `COALESCE(c_polygon, c_polygon)` polygon DEFAULT NULL,
+ `COALESCE(c_multipoint, c_multipoint)` multipoint DEFAULT NULL,
+ `COALESCE(c_multilinestring, c_multilinestring)` multilinestring DEFAULT NULL,
+ `COALESCE(c_multipolygon, c_multipolygon)` multipolygon DEFAULT NULL,
+ `COALESCE(c_geometrycollection, c_geometrycollection)` geometrycollection DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-12560 Wrong data type for SELECT NULL UNION SELECT Point(1,1)
+#
+CREATE TABLE t1 AS SELECT NULL AS c1 UNION SELECT POINT(1,1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE PROCEDURE p1(name TEXT)
+BEGIN
+EXECUTE IMMEDIATE CONCAT('CREATE TABLE t1 (a ', name, ')');
+CREATE TABLE t2 AS
+SELECT a AS a1, a AS a2, NULL AS a3 FROM t1 UNION
+SELECT a AS a1, NULL AS a2, a AS a3 FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+END;
+$$
+CALL p1('geometry');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` geometry DEFAULT NULL,
+ `a2` geometry DEFAULT NULL,
+ `a3` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('point');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` point DEFAULT NULL,
+ `a2` point DEFAULT NULL,
+ `a3` point DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('linestring');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` linestring DEFAULT NULL,
+ `a2` linestring DEFAULT NULL,
+ `a3` linestring DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('polygon');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` polygon DEFAULT NULL,
+ `a2` polygon DEFAULT NULL,
+ `a3` polygon DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('multipoint');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` multipoint DEFAULT NULL,
+ `a2` multipoint DEFAULT NULL,
+ `a3` multipoint DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('multilinestring');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` multilinestring DEFAULT NULL,
+ `a2` multilinestring DEFAULT NULL,
+ `a3` multilinestring DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('multipolygon');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` multipolygon DEFAULT NULL,
+ `a2` multipolygon DEFAULT NULL,
+ `a3` multipolygon DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CALL p1('geometrycollection');
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a1` geometrycollection DEFAULT NULL,
+ `a2` geometrycollection DEFAULT NULL,
+ `a3` geometrycollection DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+#
+# MDEV-12798 Item_param does not preserve exact field type in EXECUTE IMMEDIATE 'CREATE TABLE AS SELECT ?' USING POINT(1,1)
+#
+EXECUTE IMMEDIATE 'CREATE TABLE t1 AS SELECT ?' USING POINT(1,1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `?` point NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 AS SELECT ?';
+EXECUTE stmt USING POINT(1,1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `?` point NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+SELECT
+ST_ISSIMPLE(POINT(1,1)),
+ST_ISRING(POINT(1,1)),
+ST_ISCLOSED(POINT(1,1)),
+ST_DIMENSION(POINT(1,1)),
+ST_NUMGEOMETRIES(POINT(1,1)),
+ST_NUMINTERIORRINGS(POINT(1,1)),
+ST_NUMPOINTS(POINT(1,1)),
+ST_SRID(POINT(1,1));
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def ST_ISSIMPLE(POINT(1,1)) 3 2 1 Y 32896 0 63
+def ST_ISRING(POINT(1,1)) 3 2 2 Y 32896 0 63
+def ST_ISCLOSED(POINT(1,1)) 3 2 2 Y 32896 0 63
+def ST_DIMENSION(POINT(1,1)) 3 10 1 Y 32896 0 63
+def ST_NUMGEOMETRIES(POINT(1,1)) 3 10 0 Y 32896 0 63
+def ST_NUMINTERIORRINGS(POINT(1,1)) 3 10 0 Y 32896 0 63
+def ST_NUMPOINTS(POINT(1,1)) 3 10 0 Y 32896 0 63
+def ST_SRID(POINT(1,1)) 3 10 1 Y 32896 0 63
+ST_ISSIMPLE(POINT(1,1)) ST_ISRING(POINT(1,1)) ST_ISCLOSED(POINT(1,1)) ST_DIMENSION(POINT(1,1)) ST_NUMGEOMETRIES(POINT(1,1)) ST_NUMINTERIORRINGS(POINT(1,1)) ST_NUMPOINTS(POINT(1,1)) ST_SRID(POINT(1,1))
+1 -1 -1 0 NULL NULL NULL 0
+#
+# MDEV-12803 Improve function parameter data type control
+#
+#
+# Item_geometry_func_args_geometry
+#
+SELECT ST_CENTROID(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_centroid'
+SELECT ST_ENVELOPE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_envelope'
+SELECT ST_BOUNDARY(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_boundary'
+SELECT ST_STARTPOINT(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_startpoint'
+SELECT ST_POINTONSURFACE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_pointonsurface'
+SELECT ST_POINTN(1,1);
+ERROR HY000: Illegal parameter data type int for operation 'st_pointn'
+SELECT ST_POINTN(LineString(Point(1,1)),Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_pointn'
+SELECT ST_BUFFER(1, 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_buffer'
+SELECT ST_BUFFER(Point(1,1), Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_buffer'
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_ENVELOPE(?) AS g';
+EXECUTE stmt USING 1;
+ERROR HY000: Illegal parameter data type bigint for operation 'st_envelope'
+EXECUTE stmt USING POINT(1,1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `g` polygon DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT ST_ASTEXT(g) FROM t1;
+ST_ASTEXT(g)
+POLYGON((1 1,1 1,1 1,1 1,1 1))
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_BUFFER(?,?) AS g';
+EXECUTE stmt USING 1,1;
+ERROR HY000: Illegal parameter data type bigint for operation 'st_buffer'
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+ERROR HY000: Illegal parameter data type geometry for operation 'st_buffer'
+EXECUTE stmt USING POINT(1,1),0;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `g` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT ST_GEOMETRYTYPE(g) FROM t1;
+ST_GEOMETRYTYPE(g)
+POINT
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+#
+# Functions created GEOMETRY from non-GEOMETRY
+#
+SELECT ST_GEOMETRYFROMTEXT(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1), 1);
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMTEXT('test', Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+SELECT ST_GEOMETRYFROMWKB(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geometryfromwkb'
+SELECT ST_GEOMETRYFROMWKB(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
+SELECT ST_GEOMETRYFROMWKB(1, 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geometryfromwkb'
+SELECT ST_GEOMETRYFROMWKB(Point(1,1), Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromwkb'
+SELECT ST_GEOMFROMGEOJSON(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geomfromgeojson'
+SELECT ST_GEOMFROMGEOJSON(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geomfromgeojson'
+SELECT ST_GEOMFROMGEOJSON(1,1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geomfromgeojson'
+SELECT ST_GEOMFROMGEOJSON(Point(1,1), Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geomfromgeojson'
+SELECT POINT(ROW(1,1),1);
+ERROR HY000: Illegal parameter data type row for operation 'point'
+SELECT POINT(POINT(1,1),1);
+ERROR HY000: Illegal parameter data type geometry for operation 'point'
+SELECT POINT(1,ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'point'
+SELECT POINT(1,POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'point'
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_GEOMFROMTEXT(?,?) AS g';
+EXECUTE stmt USING 1,1;
+ERROR HY000: Illegal parameter data type bigint for operation 'st_geometryfromtext'
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+ERROR HY000: Illegal parameter data type geometry for operation 'st_geometryfromtext'
+EXECUTE stmt USING 'POINT(1 1)',1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `g` geometry DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT ST_ASTEXT(g), SRID(g) FROM t1;
+ST_ASTEXT(g) SRID(g)
+POINT(1 1) 1
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+# Item_func_spatial_collection
+SELECT GEOMETRYCOLLECTION(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'geometrycollection'
+SELECT GEOMETRYCOLLECTION(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'geometrycollection'
+SELECT GEOMETRYCOLLECTION(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
+SELECT GEOMETRYCOLLECTION(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
+# Item_func_spatial_operation
+SELECT ST_UNION(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_union'
+SELECT ST_UNION(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_union'
+SELECT ST_UNION(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'st_union'
+SELECT ST_UNION(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_union'
+# Item_binary_func_args_geometry
+SELECT ST_ASWKB(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_aswkb'
+SELECT ST_ASWKB(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_aswkb'
+SELECT ST_ASWKB('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_aswkb'
+# Item_real_func_args_geometry
+SELECT ST_X(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_x'
+SELECT ST_X(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_x'
+SELECT ST_X('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_x'
+SELECT ST_Y(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_y'
+SELECT ST_Y(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_y'
+SELECT ST_Y('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_y'
+SELECT ST_AREA(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_area'
+SELECT ST_AREA(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_area'
+SELECT ST_AREA('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_area'
+SELECT ST_LENGTH(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_length'
+SELECT ST_LENGTH(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_length'
+SELECT ST_LENGTH('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_length'
+# Item_real_func_geometry_args_geometry_geometry
+SELECT ST_DISTANCE(ROW(1,1), 1);
+ERROR HY000: Illegal parameter data type row for operation 'st_distance'
+SELECT ST_DISTANCE(1, 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_distance'
+SELECT ST_DISTANCE('test', 1);
+ERROR HY000: Illegal parameter data type varchar for operation 'st_distance'
+SELECT ST_DISTANCE(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_distance'
+SELECT ST_DISTANCE(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_distance'
+SELECT ST_DISTANCE(POINT(1,1), 'test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_distance'
+# Item_int_func_args_geometry
+SELECT ST_ISSIMPLE(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_issimple'
+SELECT ST_ISSIMPLE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_issimple'
+SELECT ST_ISSIMPLE('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_issimple'
+SELECT ST_ISRING(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_isring'
+SELECT ST_ISRING(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_isring'
+SELECT ST_ISRING('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_isring'
+SELECT ST_ISCLOSED(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_isclosed'
+SELECT ST_ISCLOSED(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_isclosed'
+SELECT ST_ISCLOSED('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_isclosed'
+SELECT ST_DIMENSION(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_dimension'
+SELECT ST_DIMENSION(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_dimension'
+SELECT ST_DIMENSION('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_dimension'
+SELECT ST_NUMGEOMETRIES(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_numgeometries'
+SELECT ST_NUMGEOMETRIES(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_numgeometries'
+SELECT ST_NUMGEOMETRIES('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_numgeometries'
+SELECT ST_NUMINTERIORRINGS(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_numinteriorrings'
+SELECT ST_NUMINTERIORRINGS(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_numinteriorrings'
+SELECT ST_NUMINTERIORRINGS('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_numinteriorrings'
+SELECT ST_NUMPOINTS(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_numpoints'
+SELECT ST_NUMPOINTS(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_numpoints'
+SELECT ST_NUMPOINTS('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_numpoints'
+SELECT ST_SRID(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'srid'
+SELECT ST_SRID(1);
+ERROR HY000: Illegal parameter data type int for operation 'srid'
+SELECT ST_SRID('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'srid'
+# Item_bool_func_args_geometry
+SELECT ST_ISEMPTY(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_isempty'
+SELECT ST_ISEMPTY(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_isempty'
+SELECT ST_ISEMPTY('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_isempty'
+# Item_bool_func_geometry_args_geometry_geometry
+SELECT ST_RELATE(ROW(1,1), POINT(1,1), 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type row for operation 'st_relate'
+SELECT ST_RELATE(POINT(1,1), ROW(1,1), 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type row for operation 'st_relate'
+SELECT ST_RELATE(1, POINT(1,1), 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type int for operation 'st_relate'
+SELECT ST_RELATE(POINT(1,1), 1, 'T*F**FFF*');
+ERROR HY000: Illegal parameter data type int for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),'T*F**FFF*') AS equals;
+equals
+1
+SELECT ST_RELATE(Point(1,1),Point(1,1),NULL);
+ST_RELATE(Point(1,1),Point(1,1),NULL)
+NULL
+SELECT ST_RELATE(Point(1,1),Point(1,1),ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),1);
+ERROR HY000: Illegal parameter data type int for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),1.0);
+ERROR HY000: Illegal parameter data type decimal for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),1e0);
+ERROR HY000: Illegal parameter data type double for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIME'10:10:10');
+ERROR HY000: Illegal parameter data type time for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),DATE'2010-01-01');
+ERROR HY000: Illegal parameter data type date for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIMESTAMP'2010-01-01 10:10:10');
+ERROR HY000: Illegal parameter data type datetime for operation 'st_relate'
+SELECT ST_RELATE(Point(1,1),Point(1,1),Point(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_relate'
+# Item_str_ascii_func_args_geometry
+SELECT ST_ASTEXT(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_astext'
+SELECT ST_ASTEXT(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_astext'
+SELECT ST_ASTEXT('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_astext'
+SELECT ST_GEOMETRYTYPE(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_geometrytype'
+SELECT ST_GEOMETRYTYPE(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_geometrytype'
+SELECT ST_GEOMETRYTYPE('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_geometrytype'
+SELECT ST_ASGEOJSON(ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON(1);
+ERROR HY000: Illegal parameter data type int for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON('test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON(POINT(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_asgeojson'
+SELECT ST_ASGEOJSON(POINT(1,1), 1, POINT(1,1));
+ERROR HY000: Illegal parameter data type geometry for operation 'st_asgeojson'
+# Item_func_spatial_rel
+SELECT ST_TOUCHES(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT ST_TOUCHES(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT ST_TOUCHES(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT ST_TOUCHES(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT ST_TOUCHES('test', POINT(1,1));
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+SELECT ST_TOUCHES(POINT(1,1), 'test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+SELECT MBRTOUCHES(ROW(1,1), POINT(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT MBRTOUCHES(POINT(1,1), ROW(1,1));
+ERROR HY000: Illegal parameter data type row for operation 'st_touches'
+SELECT MBRTOUCHES(1, POINT(1,1));
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT MBRTOUCHES(POINT(1,1), 1);
+ERROR HY000: Illegal parameter data type int for operation 'st_touches'
+SELECT MBRTOUCHES('test', POINT(1,1));
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+SELECT MBRTOUCHES(POINT(1,1), 'test');
+ERROR HY000: Illegal parameter data type varchar for operation 'st_touches'
+#
+# End of 10.3 tests
#
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index b250137ebf8..9e16cf370d8 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -1090,7 +1090,7 @@ t_nn CREATE TABLE `t_nn` (
`c1` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW CREATE VIEW mysqltest2.t_nn;
-ERROR HY000: 'mysqltest2.t_nn' is not VIEW
+ERROR HY000: 'mysqltest2.t_nn' is not of type 'VIEW'
SHOW CREATE VIEW mysqltest2.v_yy;
View Create View character_set_client collation_connection
v_yy CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v_yy` AS select `mysqltest2`.`t_nn`.`c1` AS `c1` from `mysqltest2`.`t_nn` where `mysqltest2`.`t_nn`.`c1` = 55 latin1 latin1_swedish_ci
@@ -1110,7 +1110,7 @@ t_nn CREATE TABLE `t_nn` (
`c1` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW CREATE VIEW mysqltest2.t_nn;
-ERROR HY000: 'mysqltest2.t_nn' is not VIEW
+ERROR HY000: 'mysqltest2.t_nn' is not of type 'VIEW'
DROP VIEW mysqltest2.v_nn;
DROP VIEW mysqltest2.v_yn;
DROP VIEW mysqltest2.v_ny;
@@ -1428,7 +1428,7 @@ Warnings:
Note 1305 FUNCTION test.test_function does not exist
drop view if exists v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
create table test (col1 varchar(30));
create function test_function() returns varchar(30)
begin
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index bd5f4bc1efd..d3fafe7e638 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1789,7 +1789,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t1`.`a`>((select `test`.`t1`.`a`)) AS `aa`,count(distinct `test`.`t1`.`b`) AS `COUNT(DISTINCT b)` from `test`.`t1` group by <expr_cache><`test`.`t1`.`a`>((select `test`.`t1`.`a`)) + 0
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t1`.`a`>((/* select#2 */ select `test`.`t1`.`a`)) AS `aa`,count(distinct `test`.`t1`.`b`) AS `COUNT(DISTINCT b)` from `test`.`t1` group by <expr_cache><`test`.`t1`.`a`>((/* select#2 */ select `test`.`t1`.`a`)) + 0
EXPLAIN EXTENDED
SELECT (SELECT t1.a) aa, COUNT(DISTINCT b) FROM t1 GROUP BY -aa;
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -1797,7 +1797,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t1`.`a`>((select `test`.`t1`.`a`)) AS `aa`,count(distinct `test`.`t1`.`b`) AS `COUNT(DISTINCT b)` from `test`.`t1` group by -<expr_cache><`test`.`t1`.`a`>((select `test`.`t1`.`a`))
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t1`.`a`>((/* select#2 */ select `test`.`t1`.`a`)) AS `aa`,count(distinct `test`.`t1`.`b`) AS `COUNT(DISTINCT b)` from `test`.`t1` group by -<expr_cache><`test`.`t1`.`a`>((/* select#2 */ select `test`.`t1`.`a`))
# should return only one record
SELECT (SELECT tt.a FROM t1 tt LIMIT 1) aa, COUNT(DISTINCT b) FROM t1
GROUP BY aa;
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 18fb5e2de72..4a429e1b119 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -631,7 +631,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL f10 4 NULL 2 100.00 Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having <cache>(`field1`) < 's'
+Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having <cache>(`field1`) < 's'
set optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
End of 5.2 tests
diff --git a/mysql-test/r/insert_notembedded.result b/mysql-test/r/insert_notembedded.result
index d2733eac061..8dd4aa7d71e 100644
--- a/mysql-test/r/insert_notembedded.result
+++ b/mysql-test/r/insert_notembedded.result
@@ -4,7 +4,7 @@ drop table if exists t1;
create table t1 (n int);
create view v1 as select * from t1;
insert delayed into v1 values (1);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
drop table t1;
drop view v1;
CREATE DATABASE meow;
diff --git a/mysql-test/r/intersect.result b/mysql-test/r/intersect.result
new file mode 100644
index 00000000000..5dfb7fb6875
--- /dev/null
+++ b/mysql-test/r/intersect.result
@@ -0,0 +1,691 @@
+create table t1 (a int, b int);
+create table t2 (c int, d int);
+insert into t1 values (1,1),(2,2);
+insert into t2 values (2,2),(3,3);
+(select a,b from t1) intersect (select c,d from t2);
+a b
+2 2
+drop tables t1,t2;
+create table t1 (a int, b int) engine=MyISAM;
+create table t2 (c int, d int) engine=MyISAM;
+create table t3 (e int, f int) engine=MyISAM;
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3),(4,4);
+insert into t3 values (1,1),(2,2),(5,5);
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+a b
+2 2
+EXPLAIN (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 INTERSECT t2 ALL NULL NULL NULL NULL 3
+3 INTERSECT t3 ALL NULL NULL NULL NULL 3
+NULL INTERSECT RESULT <intersect1,2,3> ALL NULL NULL NULL NULL NULL
+EXPLAIN extended (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 INTERSECT t2 ALL NULL NULL NULL NULL 3 100.00
+3 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00
+NULL INTERSECT RESULT <intersect1,2,3> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#3 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)
+EXPLAIN extended select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00
+3 INTERSECT t2 ALL NULL NULL NULL NULL 3 100.00
+4 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00
+NULL INTERSECT RESULT <intersect2,3,4> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a`
+EXPLAIN format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+EXPLAIN
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<intersect1,2,3>",
+ "access_type": "ALL",
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "INTERSECT",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "operation": "INTERSECT",
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+ANALYZE
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<intersect1,2,3>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 1,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "INTERSECT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "operation": "INTERSECT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+ANALYZE
+{
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 1,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100,
+ "materialized": {
+ "query_block": {
+ "union_result": {
+ "table_name": "<intersect2,3,4>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 1,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "operation": "INTERSECT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 4,
+ "operation": "INTERSECT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
+select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+a b
+2 2
+prepare stmt from "(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);";
+execute stmt;
+a b
+2 2
+execute stmt;
+a b
+2 2
+prepare stmt from "select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a";
+execute stmt;
+a b
+2 2
+execute stmt;
+a b
+2 2
+(select a,b from t1) intersect (select c,e from t2,t3);
+a b
+2 2
+EXPLAIN (select a,b from t1) intersect (select c,e from t2,t3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+2 INTERSECT t2 ALL NULL NULL NULL NULL 3
+2 INTERSECT t3 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join)
+NULL INTERSECT RESULT <intersect1,2> ALL NULL NULL NULL NULL NULL
+EXPLAIN extended (select a,b from t1) intersect (select c,e from t2,t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
+2 INTERSECT t2 ALL NULL NULL NULL NULL 3 100.00
+2 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
+NULL INTERSECT RESULT <intersect1,2> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)
+EXPLAIN extended select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00
+3 INTERSECT t2 ALL NULL NULL NULL NULL 3 100.00
+3 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
+NULL INTERSECT RESULT <intersect2,3> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a`
+EXPLAIN format=json (select a,b from t1) intersect (select c,e from t2,t3);
+EXPLAIN
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<intersect1,2>",
+ "access_type": "ALL",
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "INTERSECT",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL"
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json (select a,b from t1) intersect (select c,e from t2,t3);
+ANALYZE
+{
+ "query_block": {
+ "union_result": {
+ "table_name": "<intersect1,2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 1,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 2,
+ "operation": "INTERSECT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL",
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+ANALYZE format=json select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a;
+ANALYZE
+{
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 1,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100,
+ "materialized": {
+ "query_block": {
+ "union_result": {
+ "table_name": "<intersect2,3>",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "r_rows": 1,
+ "query_specifications": [
+ {
+ "query_block": {
+ "select_id": 2,
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ }
+ }
+ },
+ {
+ "query_block": {
+ "select_id": 3,
+ "operation": "INTERSECT",
+ "r_loops": 1,
+ "r_total_time_ms": "REPLACED",
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "block-nl-join": {
+ "table": {
+ "table_name": "t3",
+ "access_type": "ALL",
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 3,
+ "r_total_time_ms": "REPLACED",
+ "filtered": 100,
+ "r_filtered": 100
+ },
+ "buffer_type": "flat",
+ "buffer_size": "256Kb",
+ "join_type": "BNL",
+ "r_filtered": 100
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+}
+select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a;
+a b
+2 2
+prepare stmt from "(select a,b from t1) intersect (select c,e from t2,t3);";
+execute stmt;
+a b
+2 2
+execute stmt;
+a b
+2 2
+prepare stmt from "select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a";
+execute stmt;
+a b
+2 2
+execute stmt;
+a b
+2 2
+drop tables t1,t2,t3;
+select 1 as a from dual intersect select 1 from dual;
+a
+1
+(select 1 from dual) intersect (select 1 from dual);
+1
+1
+(select 1 from dual into @v) intersect (select 1 from dual);
+ERROR HY000: Incorrect usage of INTERSECT and INTO
+select 1 from dual ORDER BY 1 intersect select 1 from dual;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'intersect select 1 from dual' at line 1
+select 1 as a from dual union all select 1 from dual;
+a
+1
+1
+select 1 from dual intersect all select 1 from dual;
+ERROR HY000: Incorrect usage of INTERSECT and ALL
+create table t1 (a int, b blob, a1 int, b1 blob);
+create table t2 (c int, d blob, c1 int, d1 blob);
+insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt");
+insert into t2 values (2, "fgh", 2, "dffggtt"),(3, "ffggddd", 3, "dfgg");
+(select a,b,b1 from t1) intersect (select c,d,d1 from t2);
+a b b1
+2 fgh dffggtt
+drop tables t1,t2;
+create table t1 (a int, b blob) engine=MyISAM;
+create table t2 (c int, d blob) engine=MyISAM;
+create table t3 (e int, f blob) engine=MyISAM;
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3),(4,4);
+insert into t3 values (1,1),(2,2),(5,5);
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+a b
+2 2
+select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+a b
+2 2
+prepare stmt from "(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);";
+execute stmt;
+a b
+2 2
+execute stmt;
+a b
+2 2
+prepare stmt from "select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a";
+execute stmt;
+a b
+2 2
+execute stmt;
+a b
+2 2
+create table t4 (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+show create table t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `a` int(11) DEFAULT NULL,
+ `b` blob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop tables t1,t2,t3,t4;
+create table t1 (a int, b blob) engine=MyISAM;
+create table t2 (c int, d blob) engine=MyISAM;
+create table t3 (e int, f blob) engine=MyISAM;
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (1,1),(2,2),(3,3);
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+a b
+2 2
+3 3
+4 4
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4) except (select 2,2);
+a b
+3 3
+4 4
+drop tables t1,t2,t3;
+create table t1 (a int, b int);
+create table t2 (c int, d int);
+create table t3 (e int, f int);
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (1,1),(2,2),(3,3);
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+a b
+2 2
+3 3
+4 4
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4) except (select 2,2);
+a b
+3 3
+4 4
+drop tables t1,t2,t3;
+#
+# INTERSECT precedence
+#
+create table t1 (a int, b blob) engine=MyISAM;
+create table t2 (c int, d blob) engine=MyISAM;
+create table t3 (e int, f blob) engine=MyISAM;
+insert into t1 values (5,5),(6,6);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (1,1),(3,3);
+(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+a b
+3 3
+4 4
+5 5
+6 6
+explain extended
+(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+3 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00
+4 INTERSECT t3 ALL NULL NULL NULL NULL 2 100.00
+NULL INTERSECT RESULT <intersect2,4> ALL NULL NULL NULL NULL NULL NULL
+5 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+NULL UNION RESULT <union1,3,5> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#3 */ select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (/* select#5 */ select 4 AS `4`,4 AS `4`)
+(select e,f from t3) intersect (select c,d from t2) union (select a,b from t1) union (select 4,4);
+e f
+3 3
+4 4
+5 5
+6 6
+explain extended
+(select e,f from t3) intersect (select c,d from t2) union (select a,b from t1) union (select 4,4);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00
+2 INTERSECT t2 ALL NULL NULL NULL NULL 2 100.00
+3 UNION t1 ALL NULL NULL NULL NULL 2 100.00
+4 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+NULL UNIT RESULT <unit1,2,3,4> ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 (/* select#1 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`) intersect (/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) union (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union (/* select#4 */ select 4 AS `4`,4 AS `4`)
+(/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#3 */ select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (/* select#5 */ select 4 AS `4`,4 AS `4`);
+a b
+3 3
+4 4
+5 5
+6 6
+prepare stmt from "(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4)";
+execute stmt;
+a b
+5 5
+6 6
+3 3
+4 4
+execute stmt;
+a b
+5 5
+6 6
+3 3
+4 4
+create view v1 as (select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+select b,a,b+1 from v1;
+b a b+1
+3 3 4
+4 4 5
+5 5 6
+6 6 7
+select b,a,b+1 from v1 where a > 3;
+b a b+1
+4 4 5
+5 5 6
+6 6 7
+create procedure p1()
+select * from v1;
+call p1();
+a b
+3 3
+4 4
+5 5
+6 6
+call p1();
+a b
+3 3
+4 4
+5 5
+6 6
+drop procedure p1;
+create procedure p1()
+(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+call p1();
+a b
+3 3
+4 4
+5 5
+6 6
+call p1();
+a b
+3 3
+4 4
+5 5
+6 6
+drop procedure p1;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (select 4 AS `4`,4 AS `4`) latin1 latin1_swedish_ci
+drop view v1;
+drop tables t1,t2,t3;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 596cecfa8b2..df48dbba605 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -1500,7 +1500,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select NULL AS `i1`,`v2`.`i2` AS `i2`,`v2`.`a` AS `a`,`v2`.`b` AS `b` from `test`.`v2` where `v2`.`i2` = NULL and `v2`.`a` < `v2`.`b`
+Note 1003 /* select#1 */ select NULL AS `i1`,`v2`.`i2` AS `i2`,`v2`.`a` AS `a`,`v2`.`b` AS `b` from `test`.`v2` where `v2`.`i2` = NULL and `v2`.`a` < `v2`.`b`
DROP VIEW v2;
DROP TABLE t1,t2;
SET optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 571dedfd77d..46e542910a1 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -1746,7 +1746,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t3.pk 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.t2.pk' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`pk` AS `pk`,<expr_cache><`test`.`t2`.`pk`>((select `test`.`t3`.`pk` + if(`test`.`t4`.`pk` is null,0,`test`.`t4`.`pk`) from `test`.`t3` left join `test`.`t4` on(`test`.`t4`.`pk` = `test`.`t3`.`pk`) where `test`.`t3`.`pk` = `test`.`t2`.`pk` + 1000 limit 1)) AS `t` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`pk` = `test`.`t1`.`pk` + 1000 and `test`.`t1`.`pk` > 1000 group by `test`.`t2`.`pk`
+Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,<expr_cache><`test`.`t2`.`pk`>((/* select#2 */ select `test`.`t3`.`pk` + if(`test`.`t4`.`pk` is null,0,`test`.`t4`.`pk`) from `test`.`t3` left join `test`.`t4` on(`test`.`t4`.`pk` = `test`.`t3`.`pk`) where `test`.`t3`.`pk` = `test`.`t2`.`pk` + 1000 limit 1)) AS `t` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`pk` = `test`.`t1`.`pk` + 1000 and `test`.`t1`.`pk` > 1000 group by `test`.`t2`.`pk`
select t2.pk,
(select t3.pk+if(isnull(t4.pk),0,t4.pk)
from t3 left join t4 on t4.pk=t3.pk
@@ -1931,7 +1931,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00
2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select NULL AS `a` from `test`.`t2` where 1
+Note 1003 /* select#1 */ select NULL AS `a` from `test`.`t2` where 1
DROP TABLE t1,t2,t3;
#
# LP bug #817384 Wrong result with outer join + subquery in ON
diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result
index fac12729498..65e2dde409e 100644
--- a/mysql-test/r/join_outer_jcl6.result
+++ b/mysql-test/r/join_outer_jcl6.result
@@ -1757,7 +1757,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t3.pk 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.t2.pk' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`pk` AS `pk`,<expr_cache><`test`.`t2`.`pk`>((select `test`.`t3`.`pk` + if(`test`.`t4`.`pk` is null,0,`test`.`t4`.`pk`) from `test`.`t3` left join `test`.`t4` on(`test`.`t4`.`pk` = `test`.`t3`.`pk`) where `test`.`t3`.`pk` = `test`.`t2`.`pk` + 1000 limit 1)) AS `t` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`pk` = `test`.`t1`.`pk` + 1000 and `test`.`t1`.`pk` > 1000 group by `test`.`t2`.`pk`
+Note 1003 /* select#1 */ select `test`.`t2`.`pk` AS `pk`,<expr_cache><`test`.`t2`.`pk`>((/* select#2 */ select `test`.`t3`.`pk` + if(`test`.`t4`.`pk` is null,0,`test`.`t4`.`pk`) from `test`.`t3` left join `test`.`t4` on(`test`.`t4`.`pk` = `test`.`t3`.`pk`) where `test`.`t3`.`pk` = `test`.`t2`.`pk` + 1000 limit 1)) AS `t` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`pk` = `test`.`t1`.`pk` + 1000 and `test`.`t1`.`pk` > 1000 group by `test`.`t2`.`pk`
select t2.pk,
(select t3.pk+if(isnull(t4.pk),0,t4.pk)
from t3 left join t4 on t4.pk=t3.pk
@@ -1942,7 +1942,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00
2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select NULL AS `a` from `test`.`t2` where 1
+Note 1003 /* select#1 */ select NULL AS `a` from `test`.`t2` where 1
DROP TABLE t1,t2,t3;
#
# LP bug #817384 Wrong result with outer join + subquery in ON
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index 8c510b712ce..e2f29f7cfb5 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -274,7 +274,7 @@ drop table option;
set option=1;
ERROR HY000: Unknown system variable 'option'
set option option=1;
-ERROR HY000: Unknown system variable 'option'
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'option=1' at line 1
#
# MDEV-9979 Keywords UNBOUNDED, PRECEDING, FOLLOWING, TIES, OTHERS should be non-reserved
#
@@ -331,3 +331,30 @@ DROP TABLE OTHERS;
#
CREATE TABLE immediate (immediate int);
DROP TABLE immediate;
+#
+# MDEV-10142 Pluggable parser
+# Testing keywords that were added into lex.h for Oracle compatibility
+# that are not reserved keywords in MariaDB
+#
+CREATE TABLE clob (clob int);
+DROP TABLE clob;
+CREATE TABLE elsif (elsif INT);
+DROP TABLE elsif;
+CREATE TABLE exception (exception INT);
+DROP TABLE exception;
+CREATE TABLE raw (raw int);
+DROP TABLE raw;
+CREATE TABLE varchar2 (varchar2 int);
+DROP TABLE varchar2;
+CREATE TABLE decode (decode int);
+DROP TABLE decode;
+CREATE TABLE rowcount (rowcount int);
+DROP TABLE rowcount;
+CREATE TABLE isopen (isopen int);
+DROP TABLE isopen;
+CREATE TABLE notfound (notfound int);
+DROP TABLE notfound;
+CREATE TABLE raise (raise int);
+DROP TABLE raise;
+CREATE TABLE reuse (reuse int);
+DROP TABLE reuse;
diff --git a/mysql-test/r/last_value.result b/mysql-test/r/last_value.result
index b11ee6eaadb..4849effca12 100644
--- a/mysql-test/r/last_value.result
+++ b/mysql-test/r/last_value.result
@@ -21,7 +21,7 @@ a b c d
DROP TABLE t1;
SELECT LAST_VALUE(@last_a:=1,@last_b:=1);
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def LAST_VALUE(@last_a:=1,@last_b:=1) 8 1 1 N 32897 0 63
+def LAST_VALUE(@last_a:=1,@last_b:=1) 3 1 1 N 32897 0 63
LAST_VALUE(@last_a:=1,@last_b:=1)
1
select @last_b;
@@ -46,7 +46,7 @@ LAST_VALUE(@last_a:=1,@last_b:="hello")
hello
select @last_b;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @last_b 250 16777215 5 Y 0 39 8
+def @last_b 251 16777215 5 Y 0 39 8
@last_b
hello
SELECT date(LAST_VALUE(@last_a:=1,@last_b:="2001-02-03"));
@@ -56,7 +56,7 @@ date(LAST_VALUE(@last_a:=1,@last_b:="2001-02-03"))
2001-02-03
select @last_b;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @last_b 250 16777215 10 Y 0 39 8
+def @last_b 251 16777215 10 Y 0 39 8
@last_b
2001-02-03
SELECT LAST_VALUE(@last_a:=1,@last_b:="2001-02-03",NULL);
@@ -66,7 +66,7 @@ LAST_VALUE(@last_a:=1,@last_b:="2001-02-03",NULL)
NULL
select @last_b;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def @last_b 250 16777215 10 Y 0 39 8
+def @last_b 251 16777215 10 Y 0 39 8
@last_b
2001-02-03
SELECT LAST_VALUE();
diff --git a/mysql-test/r/limit_rows_examined.result b/mysql-test/r/limit_rows_examined.result
index 2b5bca2fb47..c94599235b1 100644
--- a/mysql-test/r/limit_rows_examined.result
+++ b/mysql-test/r/limit_rows_examined.result
@@ -766,6 +766,7 @@ Handler_read_rnd_deleted 0
Handler_read_rnd_next 46
SHOW STATUS LIKE 'Handler_tmp%';
Variable_name Value
+Handler_tmp_delete 0
Handler_tmp_update 0
Handler_tmp_write 66
FLUSH STATUS;
@@ -791,6 +792,7 @@ Handler_read_rnd_deleted 0
Handler_read_rnd_next 48
SHOW STATUS LIKE 'Handler_tmp%';
Variable_name Value
+Handler_tmp_delete 0
Handler_tmp_update 0
Handler_tmp_write 70
drop table t1, t2;
diff --git a/mysql-test/r/lowercase_view.result b/mysql-test/r/lowercase_view.result
index df303807407..6ccfe29b2cd 100644
--- a/mysql-test/r/lowercase_view.result
+++ b/mysql-test/r/lowercase_view.result
@@ -65,12 +65,6 @@ update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v3aA'
update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
ERROR HY000: Table 'v3aA' is specified twice, both as a target for 'UPDATE' and as a separate source for data
-delete from v2Aa where col1 = (select max(col1) from v1Aa);
-ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 'v2Aa'
-delete from v2aA where col1 = (select max(col1) from t1Aa);
-ERROR HY000: The definition of table 'v2aA' prevents operation DELETE on table 'v2aA'
-delete from v2Aa where col1 = (select max(col1) from v2aA);
-ERROR HY000: Table 'v2Aa' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
ERROR HY000: The definition of table 'v1aA' prevents operation DELETE on table 'v2aA'
delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index da194c7e11c..f55251ac199 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -629,7 +629,7 @@ INSERT INTO t3 VALUES (3), (33);
LOCK TABLES t3 READ;
CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2)
INSERT_METHOD=LAST SELECT * FROM t3;
-ERROR HY000: 'test.t4' is not BASE TABLE
+ERROR HY000: 'test.t4' is not of type 'BASE TABLE'
SELECT * FROM t4;
ERROR HY000: Table 't4' was not locked with LOCK TABLES
UNLOCK TABLES;
@@ -702,11 +702,11 @@ create table t2 (a int);
insert into t1 values (0);
insert into t2 values (1);
create table t3 engine=merge union=(t1, t2) select * from t1;
-ERROR HY000: 'test.t3' is not BASE TABLE
+ERROR HY000: 'test.t3' is not of type 'BASE TABLE'
create table t3 engine=merge union=(t1, t2) select * from t2;
-ERROR HY000: 'test.t3' is not BASE TABLE
+ERROR HY000: 'test.t3' is not of type 'BASE TABLE'
create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
-ERROR HY000: 'test.t3' is not BASE TABLE
+ERROR HY000: 'test.t3' is not of type 'BASE TABLE'
drop table t1, t2;
create table t1 (
a double(14,4),
@@ -1176,7 +1176,7 @@ SHOW CREATE TABLE t3;
ERROR 42S02: Table 'test.t3' doesn't exist
CREATE TABLE t3 ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST
SELECT * FROM t2;
-ERROR HY000: 'test.t3' is not BASE TABLE
+ERROR HY000: 'test.t3' is not of type 'BASE TABLE'
SHOW CREATE TABLE t3;
ERROR 42S02: Table 'test.t3' doesn't exist
DROP TABLE t1, t2;
@@ -3115,11 +3115,11 @@ DROP TABLE m2;
#
CREATE TABLE m2 (c1 INT, c2 INT) ENGINE=MRG_MyISAM UNION=(t3,t4)
INSERT_METHOD=LAST SELECT * FROM m1;
-ERROR HY000: 'test.m2' is not BASE TABLE
+ERROR HY000: 'test.m2' is not of type 'BASE TABLE'
#
CREATE TEMPORARY TABLE m2 (c1 INT, c2 INT) ENGINE=MRG_MyISAM UNION=(t3,t4)
INSERT_METHOD=LAST SELECT * FROM m1;
-ERROR HY000: 'test.m2' is not BASE TABLE
+ERROR HY000: 'test.m2' is not of type 'BASE TABLE'
#
CREATE TABLE m2 LIKE m1;
SHOW CREATE TABLE m2;
@@ -3519,7 +3519,7 @@ Got one of the listed errors
#
CREATE TEMPORARY TABLE m2 (c1 INT, c2 INT) ENGINE=MRG_MyISAM UNION=(t3,t4)
INSERT_METHOD=LAST SELECT * FROM m1;
-ERROR HY000: 'test.m2' is not BASE TABLE
+ERROR HY000: 'test.m2' is not of type 'BASE TABLE'
#
CREATE TEMPORARY TABLE m2 LIKE m1;
SHOW CREATE TABLE m2;
@@ -3742,34 +3742,6 @@ update m1 set a = ((select max(a) from v1));
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'm1'
update m1 set a = ((select max(a) from tmp, v1));
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'm1'
-delete from m1 where a = (select max(a) from m1);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from m2);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from t1);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from t2);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from t3, m1);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from t3, m2);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from t3, t1);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from t3, t2);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from tmp, m1);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from tmp, m2);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from tmp, t1);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from tmp, t2);
-ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
-delete from m1 where a = (select max(a) from v1);
-ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'm1'
-delete from m1 where a = (select max(a) from tmp, v1);
-ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'm1'
drop view v1;
drop temporary table tmp;
drop table t1, t2, t3, m1, m2;
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 3db3bcd450f..7848390b62e 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -1,13 +1,105 @@
drop table if exists t1,t2;
select 1, 1.0, -1, "hello", NULL;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def 1 8 1 1 N 32897 0 63
+def 1 3 1 1 N 32897 0 63
def 1.0 246 4 3 N 32897 1 63
-def -1 8 2 2 N 32897 0 63
+def -1 3 2 2 N 32897 0 63
def hello 253 5 5 N 1 39 8
def NULL 6 0 0 Y 32896 0 63
1 1.0 -1 hello NULL
1 1.0 -1 hello NULL
+SELECT
+1 AS c1,
+11 AS c2,
+111 AS c3,
+1111 AS c4,
+11111 AS c5,
+111111 AS c6,
+1111111 AS c7,
+11111111 AS c8,
+111111111 AS c9,
+1111111111 AS c10,
+11111111111 AS c11,
+111111111111 AS c12,
+1111111111111 AS c13,
+11111111111111 AS c14,
+111111111111111 AS c15,
+1111111111111111 AS c16,
+11111111111111111 AS c17,
+111111111111111111 AS c18,
+1111111111111111111 AS c19,
+11111111111111111111 AS c20,
+111111111111111111111 AS c21;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def c1 3 1 1 N 32897 0 63
+def c2 3 2 2 N 32897 0 63
+def c3 3 3 3 N 32897 0 63
+def c4 3 4 4 N 32897 0 63
+def c5 3 5 5 N 32897 0 63
+def c6 3 6 6 N 32897 0 63
+def c7 3 7 7 N 32897 0 63
+def c8 3 8 8 N 32897 0 63
+def c9 3 9 9 N 32897 0 63
+def c10 8 10 10 N 32897 0 63
+def c11 8 11 11 N 32897 0 63
+def c12 8 12 12 N 32897 0 63
+def c13 8 13 13 N 32897 0 63
+def c14 8 14 14 N 32897 0 63
+def c15 8 15 15 N 32897 0 63
+def c16 8 16 16 N 32897 0 63
+def c17 8 17 17 N 32897 0 63
+def c18 8 18 18 N 32897 0 63
+def c19 8 19 19 N 32897 0 63
+def c20 8 20 20 N 32929 0 63
+def c21 246 22 21 N 32897 0 63
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21
+1 11 111 1111 11111 111111 1111111 11111111 111111111 1111111111 11111111111 111111111111 1111111111111 11111111111111 111111111111111 1111111111111111 11111111111111111 111111111111111111 1111111111111111111 11111111111111111111 111111111111111111111
+SELECT
+-1 AS c1,
+-11 AS c2,
+-111 AS c3,
+-1111 AS c4,
+-11111 AS c5,
+-111111 AS c6,
+-1111111 AS c7,
+-11111111 AS c8,
+-111111111 AS c9,
+-1111111111 AS c10,
+-11111111111 AS c11,
+-111111111111 AS c12,
+-1111111111111 AS c13,
+-11111111111111 AS c14,
+-111111111111111 AS c15,
+-1111111111111111 AS c16,
+-11111111111111111 AS c17,
+-111111111111111111 AS c18,
+-1111111111111111111 AS c19,
+-11111111111111111111 AS c20,
+-111111111111111111111 AS c21;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def c1 3 2 2 N 32897 0 63
+def c2 3 3 3 N 32897 0 63
+def c3 3 4 4 N 32897 0 63
+def c4 3 5 5 N 32897 0 63
+def c5 3 6 6 N 32897 0 63
+def c6 3 7 7 N 32897 0 63
+def c7 3 8 8 N 32897 0 63
+def c8 3 9 9 N 32897 0 63
+def c9 8 10 10 N 32897 0 63
+def c10 8 11 11 N 32897 0 63
+def c11 8 12 12 N 32897 0 63
+def c12 8 13 13 N 32897 0 63
+def c13 8 14 14 N 32897 0 63
+def c14 8 15 15 N 32897 0 63
+def c15 8 16 16 N 32897 0 63
+def c16 8 17 17 N 32897 0 63
+def c17 8 18 18 N 32897 0 63
+def c18 8 19 19 N 32897 0 63
+def c19 8 20 20 N 32897 0 63
+def c20 246 21 21 N 32897 0 63
+def c21 246 22 22 N 32897 0 63
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21
+-1 -11 -111 -1111 -11111 -111111 -1111111 -11111111 -111111111 -1111111111 -11111111111 -111111111111 -1111111111111 -11111111111111 -111111111111111 -1111111111111111 -11111111111111111 -111111111111111111 -1111111111111111111 -11111111111111111111 -111111111111111111111
create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10));
select * from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
@@ -55,7 +147,7 @@ id data data
2 female no
select t1.id from t1 union select t2.id from t2;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def id id 1 4 1 Y 32768 0 63
+def id id 246 4 1 Y 32768 0 63
id
1
2
@@ -76,12 +168,12 @@ def aaa @arg00 @arg00 8 20 1 Y 32768 0 63
1
select 1 union select 1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def 1 1 8 20 1 N 32769 0 63
+def 1 1 3 1 1 N 32769 0 63
1
1
select * from (select 1 union select 1) aaa;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def aaa 1 1 8 20 1 N 32769 0 63
+def aaa 1 1 3 1 1 N 32769 0 63
1
1
drop table t1;
@@ -308,3 +400,405 @@ def cast('01:01:01' as time) 11 10 8 Y 128 0 63
def cast('01:01:01' as time(2)) 11 13 11 Y 128 2 63
cast('01:01:01' as time) cast('01:01:01' as time(2))
01:01:01 01:01:01.00
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+SELECT
+STRCMP('a','b'),
+OCTET_LENGTH('a'),
+CHAR_LENGTH('a'),
+COERCIBILITY('a'),
+ASCII('a'),
+ORD('a'),
+CRC32('a'),
+UNCOMPRESSED_LENGTH(COMPRESS('a'));
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def STRCMP('a','b') 3 2 2 N 32897 0 63
+def OCTET_LENGTH('a') 3 10 1 N 32897 0 63
+def CHAR_LENGTH('a') 3 10 1 N 32897 0 63
+def COERCIBILITY('a') 3 10 1 N 32897 0 63
+def ASCII('a') 3 3 2 N 32897 0 63
+def ORD('a') 3 7 2 N 32897 0 63
+def CRC32('a') 3 10 10 N 32929 0 63
+def UNCOMPRESSED_LENGTH(COMPRESS('a')) 3 10 1 Y 32896 0 63
+STRCMP('a','b') OCTET_LENGTH('a') CHAR_LENGTH('a') COERCIBILITY('a') ASCII('a') ORD('a') CRC32('a') UNCOMPRESSED_LENGTH(COMPRESS('a'))
+-1 1 1 4 97 97 3904355907 1
+SELECT
+INTERVAL(2,1,2,3),
+REGEXP_INSTR('a','a'),
+LOCATE('a','a'),
+FIND_IN_SET('b','a,b,c,d'),
+FIELD('a','a','b');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def INTERVAL(2,1,2,3) 3 2 1 N 32897 0 63
+def REGEXP_INSTR('a','a') 3 11 1 N 32897 0 63
+def LOCATE('a','a') 3 11 1 N 32897 0 63
+def FIND_IN_SET('b','a,b,c,d') 3 3 1 N 32897 0 63
+def FIELD('a','a','b') 3 3 1 N 32897 0 63
+INTERVAL(2,1,2,3) REGEXP_INSTR('a','a') LOCATE('a','a') FIND_IN_SET('b','a,b,c,d') FIELD('a','a','b')
+2 1 1 2 1
+SELECT
+SIGN(1),
+BIT_COUNT(1);
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def SIGN(1) 3 2 1 N 32897 0 63
+def BIT_COUNT(1) 3 2 1 N 32897 0 63
+SIGN(1) BIT_COUNT(1)
+1 1
+SELECT
+BENCHMARK(0,0),
+SLEEP(0);
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def BENCHMARK(0,0) 3 1 1 N 32897 0 63
+def SLEEP(0) 3 1 1 N 32897 0 63
+BENCHMARK(0,0) SLEEP(0)
+0 0
+SELECT
+GET_LOCK('metadata',0),
+IS_FREE_LOCK('metadata'),
+RELEASE_LOCK('metadata');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def GET_LOCK('metadata',0) 3 1 1 Y 32896 0 63
+def IS_FREE_LOCK('metadata') 3 1 1 Y 32896 0 63
+def RELEASE_LOCK('metadata') 3 1 1 Y 32896 0 63
+GET_LOCK('metadata',0) IS_FREE_LOCK('metadata') RELEASE_LOCK('metadata')
+1 0 1
+SELECT
+PERIOD_ADD(200801,2),
+PERIOD_DIFF(200802,200703),
+TO_DAYS('2007-10-07'),
+DAYOFMONTH('2007-02-03'),
+DAYOFWEEK('2007-02-03'),
+TO_SECONDS('2013-06-13');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def PERIOD_ADD(200801,2) 3 6 6 N 32897 0 63
+def PERIOD_DIFF(200802,200703) 3 6 2 N 32897 0 63
+def TO_DAYS('2007-10-07') 3 6 6 Y 32896 0 63
+def DAYOFMONTH('2007-02-03') 3 2 1 Y 32896 0 63
+def DAYOFWEEK('2007-02-03') 3 1 1 Y 32896 0 63
+def TO_SECONDS('2013-06-13') 8 12 11 Y 32896 0 63
+PERIOD_ADD(200801,2) PERIOD_DIFF(200802,200703) TO_DAYS('2007-10-07') DAYOFMONTH('2007-02-03') DAYOFWEEK('2007-02-03') TO_SECONDS('2013-06-13')
+200803 11 733321 3 7 63538300800
+SELECT
+YEAR('2001-02-03 04:05:06.000007'),
+DAY('2001-02-03 04:05:06.000007'),
+HOUR('2001-02-03 04:05:06.000007'),
+MINUTE('2001-02-03 04:05:06.000007'),
+SECOND('2001-02-03 04:05:06.000007'),
+MICROSECOND('2001-02-03 04:05:06.000007');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def YEAR('2001-02-03 04:05:06.000007') 3 4 4 Y 32896 0 63
+def DAY('2001-02-03 04:05:06.000007') 3 2 1 Y 32896 0 63
+def HOUR('2001-02-03 04:05:06.000007') 3 2 1 Y 32896 0 63
+def MINUTE('2001-02-03 04:05:06.000007') 3 2 1 Y 32896 0 63
+def SECOND('2001-02-03 04:05:06.000007') 3 2 1 Y 32896 0 63
+def MICROSECOND('2001-02-03 04:05:06.000007') 3 6 1 Y 32896 0 63
+YEAR('2001-02-03 04:05:06.000007') DAY('2001-02-03 04:05:06.000007') HOUR('2001-02-03 04:05:06.000007') MINUTE('2001-02-03 04:05:06.000007') SECOND('2001-02-03 04:05:06.000007') MICROSECOND('2001-02-03 04:05:06.000007')
+2001 3 4 5 6 7
+SELECT
+WEEK('2001-02-03 04:05:06.000007'),
+QUARTER('2001-02-03 04:05:06.000007'),
+YEARWEEK('2001-02-03 04:05:06.000007');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def WEEK('2001-02-03 04:05:06.000007') 3 2 1 Y 32896 0 63
+def QUARTER('2001-02-03 04:05:06.000007') 3 1 1 Y 32896 0 63
+def YEARWEEK('2001-02-03 04:05:06.000007') 3 6 6 Y 32896 0 63
+WEEK('2001-02-03 04:05:06.000007') QUARTER('2001-02-03 04:05:06.000007') YEARWEEK('2001-02-03 04:05:06.000007')
+4 1 200104
+SELECT BIT_LENGTH(10);
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def BIT_LENGTH(10) 8 11 2 N 32897 0 63
+BIT_LENGTH(10)
+16
+SELECT 1|2, 1&2, 1<<2, 1>>2, ~0, 1^2;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1|2 8 21 1 N 32929 0 63
+def 1&2 8 21 1 N 32929 0 63
+def 1<<2 8 21 1 N 32929 0 63
+def 1>>2 8 21 1 N 32929 0 63
+def ~0 8 21 20 N 32929 0 63
+def 1^2 8 21 1 N 32929 0 63
+1|2 1&2 1<<2 1>>2 ~0 1^2
+3 0 4 0 18446744073709551615 3
+SELECT LAST_INSERT_ID();
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def LAST_INSERT_ID() 8 21 1 N 32929 0 63
+LAST_INSERT_ID()
+0
+SELECT ROW_COUNT(), FOUND_ROWS();
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def ROW_COUNT() 8 21 2 N 32897 0 63
+def FOUND_ROWS() 8 21 1 N 32897 0 63
+ROW_COUNT() FOUND_ROWS()
+-1 1
+SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01') 8 21 1 Y 32896 0 63
+TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01')
+3
+#
+# MDEV-12856 Wrong result set metadata for DIV
+#
+SELECT
+2 DIV 1 AS d0l,
+222222222 DIV 1 AS d09,
+2222222222 DIV 1 AS d10;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def d0l 3 1 1 Y 32896 0 63
+def d09 3 9 9 Y 32896 0 63
+def d10 8 10 10 Y 32896 0 63
+d0l d09 d10
+2 222222222 2222222222
+#
+# MDEV-12862 Data type of @a:=1e0 depends on the session character set
+#
+SET NAMES utf8;
+CREATE TABLE t1 AS SELECT @:=1e0;
+SELECT * FROM t1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 @:=1e0 @:=1e0 5 3 1 N 36865 31 63
+@:=1e0
+1
+DROP TABLE t1;
+SET NAMES latin1;
+CREATE TABLE t1 AS SELECT @:=1e0;
+SELECT * FROM t1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 @:=1e0 @:=1e0 5 3 1 N 36865 31 63
+@:=1e0
+1
+DROP TABLE t1;
+#
+# MDEV-12869 Wrong metadata for integer additive and multiplicative operators
+#
+SELECT
+1+1,
+11+1,
+111+1,
+1111+1,
+11111+1,
+111111+1,
+1111111+1,
+11111111+1,
+111111111+1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1+1 3 3 0 N 32897 0 63
+def 11+1 3 4 0 N 32897 0 63
+def 111+1 3 5 0 N 32897 0 63
+def 1111+1 3 6 0 N 32897 0 63
+def 11111+1 3 7 0 N 32897 0 63
+def 111111+1 3 8 0 N 32897 0 63
+def 1111111+1 3 9 0 N 32897 0 63
+def 11111111+1 8 10 0 N 32897 0 63
+def 111111111+1 8 11 0 N 32897 0 63
+1+1 11+1 111+1 1111+1 11111+1 111111+1 1111111+1 11111111+1 111111111+1
+SELECT
+1-1,
+11-1,
+111-1,
+1111-1,
+11111-1,
+111111-1,
+1111111-1,
+11111111-1,
+111111111-1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1-1 3 3 0 N 32897 0 63
+def 11-1 3 4 0 N 32897 0 63
+def 111-1 3 5 0 N 32897 0 63
+def 1111-1 3 6 0 N 32897 0 63
+def 11111-1 3 7 0 N 32897 0 63
+def 111111-1 3 8 0 N 32897 0 63
+def 1111111-1 3 9 0 N 32897 0 63
+def 11111111-1 8 10 0 N 32897 0 63
+def 111111111-1 8 11 0 N 32897 0 63
+1-1 11-1 111-1 1111-1 11111-1 111111-1 1111111-1 11111111-1 111111111-1
+SELECT
+1*1,
+11*1,
+111*1,
+1111*1,
+11111*1,
+111111*1,
+1111111*1,
+11111111*1,
+111111111*1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1*1 3 3 0 N 32897 0 63
+def 11*1 3 4 0 N 32897 0 63
+def 111*1 3 5 0 N 32897 0 63
+def 1111*1 3 6 0 N 32897 0 63
+def 11111*1 3 7 0 N 32897 0 63
+def 111111*1 3 8 0 N 32897 0 63
+def 1111111*1 3 9 0 N 32897 0 63
+def 11111111*1 8 10 0 N 32897 0 63
+def 111111111*1 8 11 0 N 32897 0 63
+1*1 11*1 111*1 1111*1 11111*1 111111*1 1111111*1 11111111*1 111111111*1
+SELECT
+1 MOD 1,
+11 MOD 1,
+111 MOD 1,
+1111 MOD 1,
+11111 MOD 1,
+111111 MOD 1,
+1111111 MOD 1,
+11111111 MOD 1,
+111111111 MOD 1,
+1111111111 MOD 1,
+11111111111 MOD 1 LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def 1 MOD 1 3 1 0 Y 32896 0 63
+def 11 MOD 1 3 2 0 Y 32896 0 63
+def 111 MOD 1 3 3 0 Y 32896 0 63
+def 1111 MOD 1 3 4 0 Y 32896 0 63
+def 11111 MOD 1 3 5 0 Y 32896 0 63
+def 111111 MOD 1 3 6 0 Y 32896 0 63
+def 1111111 MOD 1 3 7 0 Y 32896 0 63
+def 11111111 MOD 1 3 8 0 Y 32896 0 63
+def 111111111 MOD 1 3 9 0 Y 32896 0 63
+def 1111111111 MOD 1 8 10 0 Y 32896 0 63
+def 11111111111 MOD 1 8 11 0 Y 32896 0 63
+1 MOD 1 11 MOD 1 111 MOD 1 1111 MOD 1 11111 MOD 1 111111 MOD 1 1111111 MOD 1 11111111 MOD 1 111111111 MOD 1 1111111111 MOD 1 11111111111 MOD 1
+SELECT
+-(1),
+-(11),
+-(111),
+-(1111),
+-(11111),
+-(111111),
+-(1111111),
+-(11111111),
+-(111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def -(1) 3 2 0 N 32897 0 63
+def -(11) 3 3 0 N 32897 0 63
+def -(111) 3 4 0 N 32897 0 63
+def -(1111) 3 5 0 N 32897 0 63
+def -(11111) 3 6 0 N 32897 0 63
+def -(111111) 3 7 0 N 32897 0 63
+def -(1111111) 3 8 0 N 32897 0 63
+def -(11111111) 3 9 0 N 32897 0 63
+def -(111111111) 8 10 0 N 32897 0 63
+-(1) -(11) -(111) -(1111) -(11111) -(111111) -(1111111) -(11111111) -(111111111)
+SELECT
+ABS(1),
+ABS(11),
+ABS(111),
+ABS(1111),
+ABS(11111),
+ABS(111111),
+ABS(1111111),
+ABS(11111111),
+ABS(111111111),
+ABS(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def ABS(1) 3 1 0 N 32897 0 63
+def ABS(11) 3 2 0 N 32897 0 63
+def ABS(111) 3 3 0 N 32897 0 63
+def ABS(1111) 3 4 0 N 32897 0 63
+def ABS(11111) 3 5 0 N 32897 0 63
+def ABS(111111) 3 6 0 N 32897 0 63
+def ABS(1111111) 3 7 0 N 32897 0 63
+def ABS(11111111) 3 8 0 N 32897 0 63
+def ABS(111111111) 3 9 0 N 32897 0 63
+def ABS(1111111111) 8 10 0 N 32897 0 63
+ABS(1) ABS(11) ABS(111) ABS(1111) ABS(11111) ABS(111111) ABS(1111111) ABS(11111111) ABS(111111111) ABS(1111111111)
+SELECT
+CEILING(1),
+CEILING(11),
+CEILING(111),
+CEILING(1111),
+CEILING(11111),
+CEILING(111111),
+CEILING(1111111),
+CEILING(11111111),
+CEILING(111111111),
+CEILING(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def CEILING(1) 3 3 0 N 32897 0 63
+def CEILING(11) 3 4 0 N 32897 0 63
+def CEILING(111) 3 5 0 N 32897 0 63
+def CEILING(1111) 3 6 0 N 32897 0 63
+def CEILING(11111) 3 7 0 N 32897 0 63
+def CEILING(111111) 3 8 0 N 32897 0 63
+def CEILING(1111111) 3 9 0 N 32897 0 63
+def CEILING(11111111) 8 10 0 N 32897 0 63
+def CEILING(111111111) 8 11 0 N 32897 0 63
+def CEILING(1111111111) 8 12 0 N 32897 0 63
+CEILING(1) CEILING(11) CEILING(111) CEILING(1111) CEILING(11111) CEILING(111111) CEILING(1111111) CEILING(11111111) CEILING(111111111) CEILING(1111111111)
+SELECT
+FLOOR(1),
+FLOOR(11),
+FLOOR(111),
+FLOOR(1111),
+FLOOR(11111),
+FLOOR(111111),
+FLOOR(1111111),
+FLOOR(11111111),
+FLOOR(111111111),
+FLOOR(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def FLOOR(1) 3 3 0 N 32897 0 63
+def FLOOR(11) 3 4 0 N 32897 0 63
+def FLOOR(111) 3 5 0 N 32897 0 63
+def FLOOR(1111) 3 6 0 N 32897 0 63
+def FLOOR(11111) 3 7 0 N 32897 0 63
+def FLOOR(111111) 3 8 0 N 32897 0 63
+def FLOOR(1111111) 3 9 0 N 32897 0 63
+def FLOOR(11111111) 8 10 0 N 32897 0 63
+def FLOOR(111111111) 8 11 0 N 32897 0 63
+def FLOOR(1111111111) 8 12 0 N 32897 0 63
+FLOOR(1) FLOOR(11) FLOOR(111) FLOOR(1111) FLOOR(11111) FLOOR(111111) FLOOR(1111111) FLOOR(11111111) FLOOR(111111111) FLOOR(1111111111)
+SELECT
+ROUND(1),
+ROUND(11),
+ROUND(111),
+ROUND(1111),
+ROUND(11111),
+ROUND(111111),
+ROUND(1111111),
+ROUND(11111111),
+ROUND(111111111),
+ROUND(1111111111) LIMIT 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def ROUND(1) 3 1 0 N 32897 0 63
+def ROUND(11) 3 2 0 N 32897 0 63
+def ROUND(111) 3 3 0 N 32897 0 63
+def ROUND(1111) 3 4 0 N 32897 0 63
+def ROUND(11111) 3 5 0 N 32897 0 63
+def ROUND(111111) 3 6 0 N 32897 0 63
+def ROUND(1111111) 3 7 0 N 32897 0 63
+def ROUND(11111111) 3 8 0 N 32897 0 63
+def ROUND(111111111) 3 9 0 N 32897 0 63
+def ROUND(1111111111) 8 10 0 N 32897 0 63
+ROUND(1) ROUND(11) ROUND(111) ROUND(1111) ROUND(11111) ROUND(111111) ROUND(1111111) ROUND(11111111) ROUND(111111111) ROUND(1111111111)
+#
+# MDEV-12546 Wrong metadata or data type for string user variables
+#
+SET @a='test';
+SELECT @a;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def @a 251 16777215 4 Y 0 39 8
+@a
+test
+CREATE TABLE t1 AS SELECT @a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@a` longtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SELECT @b1:=10, @b2:=@b2:=111111111111;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def @b1:=10 3 2 2 N 32897 0 63
+def @b2:=@b2:=111111111111 8 12 12 N 32897 0 63
+@b1:=10 @b2:=@b2:=111111111111
+10 111111111111
+CREATE TABLE t1 AS SELECT @b1:=10, @b2:=111111111111;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `@b1:=10` int(2) NOT NULL,
+ `@b2:=111111111111` bigint(12) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/r/myisam_explain_non_select_all.result b/mysql-test/r/myisam_explain_non_select_all.result
index e60bb9a8d08..12c5e627f7a 100644
--- a/mysql-test/r/myisam_explain_non_select_all.result
+++ b/mysql-test/r/myisam_explain_non_select_all.result
@@ -397,7 +397,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t11 ALL NULL NULL NULL NULL 3 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t11`.`a` AS `a`,1 AS `1` from `test`.`t1` `t11`
+Note 1003 /* select#1 */ select `test`.`t11`.`a` AS `a`,1 AS `1` from `test`.`t1` `t11`
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
Handler_read_rnd_next 1
@@ -888,7 +888,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(select `test`.`t2`.`a2` from `test`.`t2` where `test`.`t2`.`a2` > 2 and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where `test`.`t2`.`a2` > 2 and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`)))
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
# Status of "equivalent" SELECT query execution:
@@ -2281,7 +2281,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ALL IDX NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t1`.`f1`>((select max(`test`.`t2`.`f4`) from `test`.`t2` where `test`.`t2`.`f3` = `test`.`t1`.`f1`)) AS `(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1)` from `test`.`t1`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t1`.`f1`>((/* select#2 */ select max(`test`.`t2`.`f4`) from `test`.`t2` where `test`.`t2`.`f3` = `test`.`t1`.`f1`)) AS `(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1)` from `test`.`t1`
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
# Status of "equivalent" SELECT query execution:
@@ -2637,7 +2637,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join ((select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join ((/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) where 1
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
# Status of "equivalent" SELECT query execution:
@@ -2688,7 +2688,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where 1
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
# Status of "equivalent" SELECT query execution:
@@ -2740,7 +2740,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 3 100.00
4 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((/* select#4 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where 1
# Status of EXPLAIN EXTENDED "equivalent" SELECT query execution
Variable_name Value
# Status of "equivalent" SELECT query execution:
diff --git a/mysql-test/r/myisam_mrr.result b/mysql-test/r/myisam_mrr.result
index bd50df7c40e..511e6a8d01f 100644
--- a/mysql-test/r/myisam_mrr.result
+++ b/mysql-test/r/myisam_mrr.result
@@ -354,7 +354,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t2 ref int_key int_key 5 const 1 100.00 Using index condition
Warnings:
-Note 1003 select min(`test`.`t1`.`pk`) AS `MIN(t1.pk)` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select min(`test`.`t1`.`pk`) AS `MIN(t1.pk)` from `test`.`t1` where 0
DROP TABLE t1, t2;
#
# BUG#42048 Discrepancy between MyISAM and Maria's ICP implementation
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 8716274dd4b..2baf4f6c314 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -1405,7 +1405,7 @@ performance-schema-max-rwlock-instances -1
performance-schema-max-socket-classes 10
performance-schema-max-socket-instances -1
performance-schema-max-stage-classes 150
-performance-schema-max-statement-classes 188
+performance-schema-max-statement-classes 191
performance-schema-max-table-handles -1
performance-schema-max-table-instances -1
performance-schema-max-thread-classes 50
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 0ff5c3243d8..2fa89a2d001 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -575,8 +575,14 @@ c_float FLOAT,
c_double DOUBLE,
c_decimal103 DECIMAL(10,3),
c_varchar10 VARCHAR(10),
+c_tinytext TINYTEXT,
c_text TEXT,
+c_mediumtext MEDIUMTEXT,
+c_longtext LONGTEXT,
+c_tinyblob TINYBLOB,
c_blob BLOB,
+c_mediumblob MEDIUMBLOB,
+c_longblob LONGBLOB,
c_enum ENUM('one','two','tree'),
c_datetime3 DATETIME(3),
c_timestamp3 TIMESTAMP(3),
@@ -607,22 +613,22 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `NULLIF(c_tinyint, 1)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_smallint)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_tinyint)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_int)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_bigint)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_float)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_double)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_decimal103)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_varchar10)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_text)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_blob)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_enum)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_datetime3)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_timestamp3)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_date)` int(4) DEFAULT NULL,
- `NULLIF(c_tinyint, c_time)` int(4) DEFAULT NULL
+ `NULLIF(c_tinyint, 1)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_smallint)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_tinyint)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_int)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_bigint)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_float)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_double)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_decimal103)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_varchar10)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_text)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_blob)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_enum)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_datetime3)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_timestamp3)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_date)` tinyint(4) DEFAULT NULL,
+ `NULLIF(c_tinyint, c_time)` tinyint(4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
@@ -646,22 +652,22 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `NULLIF(c_smallint, 1)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_smallint)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_tinyint)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_int)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_bigint)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_float)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_double)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_decimal103)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_varchar10)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_text)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_blob)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_enum)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_datetime3)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_timestamp3)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_date)` int(6) DEFAULT NULL,
- `NULLIF(c_smallint, c_time)` int(6) DEFAULT NULL
+ `NULLIF(c_smallint, 1)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_smallint)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_tinyint)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_int)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_bigint)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_float)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_double)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_decimal103)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_varchar10)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_text)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_blob)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_enum)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_datetime3)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_timestamp3)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_date)` smallint(6) DEFAULT NULL,
+ `NULLIF(c_smallint, c_time)` smallint(6) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
@@ -763,22 +769,22 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `NULLIF(c_float, 1)` double DEFAULT NULL,
- `NULLIF(c_float, c_smallint)` double DEFAULT NULL,
- `NULLIF(c_float, c_tinyint)` double DEFAULT NULL,
- `NULLIF(c_float, c_int)` double DEFAULT NULL,
- `NULLIF(c_float, c_bigint)` double DEFAULT NULL,
- `NULLIF(c_float, c_float)` double DEFAULT NULL,
- `NULLIF(c_float, c_double)` double DEFAULT NULL,
- `NULLIF(c_float, c_decimal103)` double DEFAULT NULL,
- `NULLIF(c_float, c_varchar10)` double DEFAULT NULL,
- `NULLIF(c_float, c_text)` double DEFAULT NULL,
- `NULLIF(c_float, c_blob)` double DEFAULT NULL,
- `NULLIF(c_float, c_enum)` double DEFAULT NULL,
- `NULLIF(c_float, c_datetime3)` double DEFAULT NULL,
- `NULLIF(c_float, c_timestamp3)` double DEFAULT NULL,
- `NULLIF(c_float, c_date)` double DEFAULT NULL,
- `NULLIF(c_float, c_time)` double DEFAULT NULL
+ `NULLIF(c_float, 1)` float DEFAULT NULL,
+ `NULLIF(c_float, c_smallint)` float DEFAULT NULL,
+ `NULLIF(c_float, c_tinyint)` float DEFAULT NULL,
+ `NULLIF(c_float, c_int)` float DEFAULT NULL,
+ `NULLIF(c_float, c_bigint)` float DEFAULT NULL,
+ `NULLIF(c_float, c_float)` float DEFAULT NULL,
+ `NULLIF(c_float, c_double)` float DEFAULT NULL,
+ `NULLIF(c_float, c_decimal103)` float DEFAULT NULL,
+ `NULLIF(c_float, c_varchar10)` float DEFAULT NULL,
+ `NULLIF(c_float, c_text)` float DEFAULT NULL,
+ `NULLIF(c_float, c_blob)` float DEFAULT NULL,
+ `NULLIF(c_float, c_enum)` float DEFAULT NULL,
+ `NULLIF(c_float, c_datetime3)` float DEFAULT NULL,
+ `NULLIF(c_float, c_timestamp3)` float DEFAULT NULL,
+ `NULLIF(c_float, c_date)` float DEFAULT NULL,
+ `NULLIF(c_float, c_time)` float DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
@@ -899,6 +905,45 @@ t2 CREATE TABLE `t2` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
+NULLIF(c_tinytext, 1),
+NULLIF(c_tinytext, c_smallint),
+NULLIF(c_tinytext, c_tinyint),
+NULLIF(c_tinytext, c_int),
+NULLIF(c_tinytext, c_bigint),
+NULLIF(c_tinytext, c_float),
+NULLIF(c_tinytext, c_double),
+NULLIF(c_tinytext, c_decimal103),
+NULLIF(c_tinytext, c_varchar10),
+NULLIF(c_tinytext, c_text),
+NULLIF(c_tinytext, c_blob),
+NULLIF(c_tinytext, c_enum),
+NULLIF(c_tinytext, c_datetime3),
+NULLIF(c_tinytext, c_timestamp3),
+NULLIF(c_tinytext, c_date),
+NULLIF(c_tinytext, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `NULLIF(c_tinytext, 1)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_smallint)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_tinyint)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_int)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_bigint)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_float)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_double)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_decimal103)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_varchar10)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_text)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_blob)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_enum)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_datetime3)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_timestamp3)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_date)` tinytext DEFAULT NULL,
+ `NULLIF(c_tinytext, c_time)` tinytext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
NULLIF(c_text, 1),
NULLIF(c_text, c_smallint),
NULLIF(c_text, c_tinyint),
@@ -919,22 +964,139 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `NULLIF(c_text, 1)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_smallint)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_tinyint)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_int)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_bigint)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_float)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_double)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_decimal103)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_varchar10)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_text)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_blob)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_enum)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_datetime3)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_timestamp3)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_date)` longtext DEFAULT NULL,
- `NULLIF(c_text, c_time)` longtext DEFAULT NULL
+ `NULLIF(c_text, 1)` text DEFAULT NULL,
+ `NULLIF(c_text, c_smallint)` text DEFAULT NULL,
+ `NULLIF(c_text, c_tinyint)` text DEFAULT NULL,
+ `NULLIF(c_text, c_int)` text DEFAULT NULL,
+ `NULLIF(c_text, c_bigint)` text DEFAULT NULL,
+ `NULLIF(c_text, c_float)` text DEFAULT NULL,
+ `NULLIF(c_text, c_double)` text DEFAULT NULL,
+ `NULLIF(c_text, c_decimal103)` text DEFAULT NULL,
+ `NULLIF(c_text, c_varchar10)` text DEFAULT NULL,
+ `NULLIF(c_text, c_text)` text DEFAULT NULL,
+ `NULLIF(c_text, c_blob)` text DEFAULT NULL,
+ `NULLIF(c_text, c_enum)` text DEFAULT NULL,
+ `NULLIF(c_text, c_datetime3)` text DEFAULT NULL,
+ `NULLIF(c_text, c_timestamp3)` text DEFAULT NULL,
+ `NULLIF(c_text, c_date)` text DEFAULT NULL,
+ `NULLIF(c_text, c_time)` text DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+NULLIF(c_mediumtext, 1),
+NULLIF(c_mediumtext, c_smallint),
+NULLIF(c_mediumtext, c_tinyint),
+NULLIF(c_mediumtext, c_int),
+NULLIF(c_mediumtext, c_bigint),
+NULLIF(c_mediumtext, c_float),
+NULLIF(c_mediumtext, c_double),
+NULLIF(c_mediumtext, c_decimal103),
+NULLIF(c_mediumtext, c_varchar10),
+NULLIF(c_mediumtext, c_text),
+NULLIF(c_mediumtext, c_blob),
+NULLIF(c_mediumtext, c_enum),
+NULLIF(c_mediumtext, c_datetime3),
+NULLIF(c_mediumtext, c_timestamp3),
+NULLIF(c_mediumtext, c_date),
+NULLIF(c_mediumtext, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `NULLIF(c_mediumtext, 1)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_smallint)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_tinyint)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_int)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_bigint)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_float)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_double)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_decimal103)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_varchar10)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_text)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_blob)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_enum)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_datetime3)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_timestamp3)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_date)` mediumtext DEFAULT NULL,
+ `NULLIF(c_mediumtext, c_time)` mediumtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+NULLIF(c_longtext, 1),
+NULLIF(c_longtext, c_smallint),
+NULLIF(c_longtext, c_tinyint),
+NULLIF(c_longtext, c_int),
+NULLIF(c_longtext, c_bigint),
+NULLIF(c_longtext, c_float),
+NULLIF(c_longtext, c_double),
+NULLIF(c_longtext, c_decimal103),
+NULLIF(c_longtext, c_varchar10),
+NULLIF(c_longtext, c_text),
+NULLIF(c_longtext, c_blob),
+NULLIF(c_longtext, c_enum),
+NULLIF(c_longtext, c_datetime3),
+NULLIF(c_longtext, c_timestamp3),
+NULLIF(c_longtext, c_date),
+NULLIF(c_longtext, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `NULLIF(c_longtext, 1)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_smallint)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_tinyint)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_int)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_bigint)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_float)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_double)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_decimal103)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_varchar10)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_text)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_blob)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_enum)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_datetime3)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_timestamp3)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_date)` longtext DEFAULT NULL,
+ `NULLIF(c_longtext, c_time)` longtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+NULLIF(c_tinyblob, 1),
+NULLIF(c_tinyblob, c_smallint),
+NULLIF(c_tinyblob, c_tinyint),
+NULLIF(c_tinyblob, c_int),
+NULLIF(c_tinyblob, c_bigint),
+NULLIF(c_tinyblob, c_float),
+NULLIF(c_tinyblob, c_double),
+NULLIF(c_tinyblob, c_decimal103),
+NULLIF(c_tinyblob, c_varchar10),
+NULLIF(c_tinyblob, c_text),
+NULLIF(c_tinyblob, c_blob),
+NULLIF(c_tinyblob, c_enum),
+NULLIF(c_tinyblob, c_datetime3),
+NULLIF(c_tinyblob, c_timestamp3),
+NULLIF(c_tinyblob, c_date),
+NULLIF(c_tinyblob, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `NULLIF(c_tinyblob, 1)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_smallint)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_tinyint)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_int)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_bigint)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_float)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_double)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_decimal103)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_varchar10)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_text)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_blob)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_enum)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_datetime3)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_timestamp3)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_date)` tinyblob DEFAULT NULL,
+ `NULLIF(c_tinyblob, c_time)` tinyblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
@@ -958,22 +1120,100 @@ FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `NULLIF(c_blob, 1)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_smallint)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_tinyint)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_int)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_bigint)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_float)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_double)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_decimal103)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_varchar10)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_text)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_blob)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_enum)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_datetime3)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_timestamp3)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_date)` longblob DEFAULT NULL,
- `NULLIF(c_blob, c_time)` longblob DEFAULT NULL
+ `NULLIF(c_blob, 1)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_smallint)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_tinyint)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_int)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_bigint)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_float)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_double)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_decimal103)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_varchar10)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_text)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_blob)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_enum)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_datetime3)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_timestamp3)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_date)` blob DEFAULT NULL,
+ `NULLIF(c_blob, c_time)` blob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+NULLIF(c_mediumblob, 1),
+NULLIF(c_mediumblob, c_smallint),
+NULLIF(c_mediumblob, c_tinyint),
+NULLIF(c_mediumblob, c_int),
+NULLIF(c_mediumblob, c_bigint),
+NULLIF(c_mediumblob, c_float),
+NULLIF(c_mediumblob, c_double),
+NULLIF(c_mediumblob, c_decimal103),
+NULLIF(c_mediumblob, c_varchar10),
+NULLIF(c_mediumblob, c_text),
+NULLIF(c_mediumblob, c_blob),
+NULLIF(c_mediumblob, c_enum),
+NULLIF(c_mediumblob, c_datetime3),
+NULLIF(c_mediumblob, c_timestamp3),
+NULLIF(c_mediumblob, c_date),
+NULLIF(c_mediumblob, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `NULLIF(c_mediumblob, 1)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_smallint)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_tinyint)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_int)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_bigint)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_float)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_double)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_decimal103)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_varchar10)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_text)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_blob)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_enum)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_datetime3)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_timestamp3)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_date)` mediumblob DEFAULT NULL,
+ `NULLIF(c_mediumblob, c_time)` mediumblob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+NULLIF(c_longblob, 1),
+NULLIF(c_longblob, c_smallint),
+NULLIF(c_longblob, c_tinyint),
+NULLIF(c_longblob, c_int),
+NULLIF(c_longblob, c_bigint),
+NULLIF(c_longblob, c_float),
+NULLIF(c_longblob, c_double),
+NULLIF(c_longblob, c_decimal103),
+NULLIF(c_longblob, c_varchar10),
+NULLIF(c_longblob, c_text),
+NULLIF(c_longblob, c_blob),
+NULLIF(c_longblob, c_enum),
+NULLIF(c_longblob, c_datetime3),
+NULLIF(c_longblob, c_timestamp3),
+NULLIF(c_longblob, c_date),
+NULLIF(c_longblob, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `NULLIF(c_longblob, 1)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_smallint)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_tinyint)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_int)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_bigint)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_float)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_double)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_decimal103)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_varchar10)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_text)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_blob)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_enum)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_datetime3)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_timestamp3)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_date)` longblob DEFAULT NULL,
+ `NULLIF(c_longblob, c_time)` longblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index b10f175b63e..bcc96d4951d 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -696,8 +696,8 @@ CREATE VIEW v1 AS
SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
DESC v1;
Field Type Null Key Default Extra
-a bigint(11) YES NULL
-LENGTH(a) bigint(10) YES NULL
+a int(11) YES 0
+LENGTH(a) int(10) YES NULL
COUNT(*) bigint(21) NO 0
SELECT * FROM v1;
a LENGTH(a) COUNT(*)
@@ -766,3 +766,53 @@ b
NULL
DROP TABLE t1, t2;
End of 5.0 tests
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12886 Different default for INT and BIGINT column in a VIEW for a SELECT with ROLLUP
+#
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+CREATE OR REPLACE VIEW v1 AS SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
+DESCRIBE v1;
+Field Type Null Key Default Extra
+a int(11) YES 0
+LENGTH(a) int(10) YES NULL
+COUNT(*) bigint(21) NO 0
+DROP VIEW v1;
+DROP TABLE t1;
+CREATE TABLE t1 (a bigint(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+CREATE OR REPLACE VIEW v1 AS SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
+DESCRIBE v1;
+Field Type Null Key Default Extra
+a bigint(20) YES 0
+LENGTH(a) int(10) YES NULL
+COUNT(*) bigint(21) NO 0
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# MDEV-9410 VIEW over a ROLLUP query reports too large columns
+#
+CREATE TABLE t1 (a int(10) NOT NULL, b int(20) NOT NULL);
+INSERT INTO t1 VALUES (1,1),(2,2);
+CREATE VIEW v1 AS SELECT a,b FROM t1;
+DESC v1;
+Field Type Null Key Default Extra
+a int(10) NO NULL
+b int(20) NO NULL
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT a, b FROM t1 GROUP BY a,b;
+DESC v1;
+Field Type Null Key Default Extra
+a int(10) NO NULL
+b int(20) NO NULL
+DROP VIEW v1;
+CREATE VIEW v1 AS SELECT a, b FROM t1 GROUP BY a,b WITH ROLLUP;
+DESC v1;
+Field Type Null Key Default Extra
+a int(11) YES 0
+b int(20) YES 0
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result
index 6029a976ba3..f197fbe6a19 100644
--- a/mysql-test/r/parser.result
+++ b/mysql-test/r/parser.result
@@ -1319,3 +1319,12 @@ t1 CREATE TABLE `t1` (
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
+#
+# MDEV-10343 Providing compatibility for basic SQL data types
+#
+CREATE TABLE clob (clob int);
+DROP TABLE clob;
+CREATE TABLE raw (raw int);
+DROP TABLE raw;
+CREATE TABLE varchar2 (varchar2 int);
+DROP TABLE varchar2;
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index cc77218575d..f398ef07d56 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -2439,7 +2439,7 @@ SELECT 1 FROM t1 WHERE b < SOME
GROUP BY b WITH ROLLUP
HAVING b > geomfromtext("")
);
-1
+ERROR HY000: Illegal parameter data types mediumint and geometry for operation '>'
DROP TABLE t1;
MDEV-612 Valgrind error in ha_maria::check_if_incompatible_data
diff --git a/mysql-test/r/partition_column.result b/mysql-test/r/partition_column.result
index 067245fc682..041c485c1a8 100644
--- a/mysql-test/r/partition_column.result
+++ b/mysql-test/r/partition_column.result
@@ -542,7 +542,7 @@ create table t1 as select to_seconds(null) as to_seconds;
select data_type from information_schema.columns
where table_schema='test' and column_name='to_seconds';
data_type
-int
+bigint
drop table t1;
create table t1 (a int, b int)
partition by list columns(a,b)
diff --git a/mysql-test/r/partition_explicit_prune.result b/mysql-test/r/partition_explicit_prune.result
index a29f1aa7a8a..bfcfe7deef6 100644
--- a/mysql-test/r/partition_explicit_prune.result
+++ b/mysql-test/r/partition_explicit_prune.result
@@ -19,7 +19,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_RND_NEXT 3
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 4 locks (1 table, 1 partition lock/unlock)
FLUSH STATUS;
SELECT a FROM t1 PARTITION (p0);
@@ -31,7 +31,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_RND_NEXT 3
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 4 locks (1 table, 1 partition lock/unlock)
FLUSH STATUS;
INSERT INTO v1 VALUES (10);
@@ -39,14 +39,14 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 2
# 4 locks (1 table, 1 partition lock/unlock)
FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 2 locks (1 table, all partitions pruned)
FLUSH STATUS;
SELECT * FROM v1;
@@ -59,7 +59,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_RND_NEXT 4
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 4 locks (1 table, 1 partition lock/unlock)
FLUSH STATUS;
SELECT a FROM t1 PARTITION (p0);
@@ -72,7 +72,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_RND_NEXT 4
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 4 locks (1 table, 1 partition lock/unlock)
SELECT * FROM t1;
a
@@ -89,14 +89,14 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 2
# 4 locks (1 table, 1 partition lock/unlock)
FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 2 locks (1 table, all partitions pruned)
SELECT * FROM v1;
a
@@ -121,7 +121,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 2
# 4 locks (1 table, 1 partition lock/unlock)
FLUSH STATUS;
@@ -131,7 +131,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 2 locks (1 table, all partitions pruned)
FLUSH STATUS;
INSERT INTO v1 VALUES (32);
@@ -140,7 +140,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 4 locks (1 table, 1 partition lock/unlock)
SELECT * FROM v1;
a
@@ -166,12 +166,12 @@ FLUSH STATUS;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
# OK, seems to add number of variables processed before HANDLER_WRITE
# and number of variables + 1 evaluated in the previous call in RND_NEXT
CREATE TABLE t1
@@ -233,7 +233,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 2
# Should be 1 commit
# 4 external locks (due to pruning of locks)
@@ -250,7 +250,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 2
# Should be 1 commit
# 4 external locks
@@ -262,7 +262,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# should be 1 commit
# 9 locks (1 ha_partition + 8 ha_innobase)
# 17 writes (internal I_S)
@@ -271,8 +271,8 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
HANDLER_WRITE 2
# + 1 commit
# + 19 rnd next (internal I_S)
@@ -282,8 +282,8 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
-HANDLER_READ_RND_NEXT 54
-HANDLER_TMP_WRITE 75
+HANDLER_READ_RND_NEXT 56
+HANDLER_TMP_WRITE 78
HANDLER_WRITE 2
# + 9 locks (unlocks)
# + 19 rnd next (internal I_S)
@@ -338,7 +338,7 @@ ERROR HY000: Unknown partition 'pNonexistent' in table 't1'
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# should have failed before locking (only 17 internal I_S writes)
FLUSH STATUS;
SELECT * FROM t1 PARTITION (subp2);
@@ -348,7 +348,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Should be 1 commit
# 4 locks (1 ha_partition + 1 ha_innobase) x 2 (lock/unlock)
# 1 read first (also calls index_read)
@@ -366,7 +366,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 3
HANDLER_READ_NEXT 3
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Should be 1 commit
# 8 locks (1 ha_partition + 2 + 1 ha_innobase) x 2
# 3 read first (one for each partition)
@@ -379,7 +379,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 1 commit
# 18 locks
# 18 READ KEY from opening a new partition table instance,
@@ -398,8 +398,8 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
HANDLER_READ_FIRST 1
HANDLER_READ_NEXT 3
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
# + 1 commit
# + 1 read first (read first key from index in one partition)
# + 2 read key (innobase_get_index from index_init + from index_first)
@@ -415,8 +415,8 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 3
HANDLER_READ_FIRST 3
HANDLER_READ_NEXT 4
-HANDLER_READ_RND_NEXT 54
-HANDLER_TMP_WRITE 75
+HANDLER_READ_RND_NEXT 56
+HANDLER_TMP_WRITE 78
# + 1 commit
# + 2 read first (one for each subpart)
# + 4 read key (innobase_get_index from index_init + from index_first)
@@ -431,8 +431,8 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 4
HANDLER_READ_FIRST 3
HANDLER_READ_NEXT 4
-HANDLER_READ_RND_NEXT 81
-HANDLER_TMP_WRITE 101
+HANDLER_READ_RND_NEXT 84
+HANDLER_TMP_WRITE 105
# No matching partition, only internal I_S.
SELECT * FROM t1 PARTITION (pNeg) WHERE a = 100;
a b
@@ -443,8 +443,8 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 5
HANDLER_READ_FIRST 3
HANDLER_READ_NEXT 4
-HANDLER_READ_RND_NEXT 108
-HANDLER_TMP_WRITE 127
+HANDLER_READ_RND_NEXT 112
+HANDLER_TMP_WRITE 132
# + 18 for unlock (same as lock above) (100 is not in pNeg, no match)
# Test that EXPLAIN PARTITION works
EXPLAIN PARTITIONS SELECT * FROM t1 PARTITION (pNonexistent);
@@ -460,7 +460,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 8 locks (1 ha_partition + 3 ha_innobase) x 2 (lock/unlock)
EXPLAIN PARTITIONS SELECT * FROM t1 PARTITION (subp3) AS TableAlias;
id select_type table partitions type possible_keys key key_len ref rows Extra
@@ -513,7 +513,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 1
# 2 locks (1 ha_partition) x 2 (lock/unlock), Was 4 locks before WL4443
# explicit pruning says part_id 0 and implicit pruning says part_id 1
@@ -526,7 +526,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 2
# 1 commit
# 4 locks (1 ha_partition + 1 ha_innobase) x 2 (lock/unlock)
@@ -544,7 +544,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_KEY 2
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 2
HANDLER_WRITE 2
# 1 commit
@@ -566,7 +566,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 1 commit
# 9 locks
# 17 write (internal I_S)
@@ -578,8 +578,8 @@ HANDLER_COMMIT 2
HANDLER_DELETE 2
HANDLER_READ_KEY 1
HANDLER_READ_NEXT 1
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
# + 1 commit
# + 1 delete (one row deleted)
# + 3 read key (1 innodb_get_index in records_in_range,
@@ -596,9 +596,9 @@ HANDLER_COMMIT 2
HANDLER_DELETE 2
HANDLER_READ_KEY 1
HANDLER_READ_NEXT 1
-HANDLER_READ_RND_NEXT 54
+HANDLER_READ_RND_NEXT 56
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 75
+HANDLER_TMP_WRITE 78
HANDLER_WRITE 1
# Failed before start_stmt/execution.
# + 19 rnd next (internal I_S)
@@ -612,9 +612,9 @@ HANDLER_COMMIT 3
HANDLER_DELETE 2
HANDLER_READ_KEY 1
HANDLER_READ_NEXT 1
-HANDLER_READ_RND_NEXT 81
+HANDLER_READ_RND_NEXT 84
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 101
+HANDLER_TMP_WRITE 105
HANDLER_WRITE 3
# + 1 commit
# + 19 rnd next (internal I_S)
@@ -627,9 +627,9 @@ HANDLER_COMMIT 4
HANDLER_DELETE 2
HANDLER_READ_KEY 3
HANDLER_READ_NEXT 1
-HANDLER_READ_RND_NEXT 108
+HANDLER_READ_RND_NEXT 112
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 127
+HANDLER_TMP_WRITE 132
HANDLER_UPDATE 2
HANDLER_WRITE 5
# + 1 commit
@@ -650,9 +650,9 @@ HANDLER_DELETE 2
HANDLER_READ_FIRST 1
HANDLER_READ_KEY 3
HANDLER_READ_NEXT 4
-HANDLER_READ_RND_NEXT 135
+HANDLER_READ_RND_NEXT 140
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 153
+HANDLER_TMP_WRITE 159
HANDLER_UPDATE 2
HANDLER_WRITE 5
# + 1 commit
@@ -670,9 +670,9 @@ HANDLER_DELETE 2
HANDLER_READ_FIRST 1
HANDLER_READ_KEY 3
HANDLER_READ_NEXT 4
-HANDLER_READ_RND_NEXT 162
+HANDLER_READ_RND_NEXT 168
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 179
+HANDLER_TMP_WRITE 186
HANDLER_UPDATE 2
HANDLER_WRITE 5
# + 9 locks
@@ -696,7 +696,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 4
HANDLER_READ_NEXT 5
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 1 commit
# 10 locks (1 ha_partition + 4 ha_innobase) x 2 (lock/unlock)
# 4 read first (for reading the first row in 4 partitions)
@@ -709,7 +709,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 10 locks (table + 4 partition) x (lock + unlock)
SELECT * FROM t1 PARTITION (pNeg, `p10-99`);
a b
@@ -720,7 +720,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 3
# 6 locks (1 ha_partition + 2 ha_innobase) x 2 (lock+unlock)
# 1 rollback
@@ -732,7 +732,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 10
# 10 lock (1 ha_partition + 4 ha_innobase) x 2 (lock + unlock)
ALTER TABLE t1 TRUNCATE PARTITION pNeg, `p10-99`;
@@ -742,7 +742,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 9 locks
# 18 read key (ALTER forces table to be closed, see above for open)
LOAD DATA INFILE 'loadtest.txt' INTO TABLE t1 PARTITION (pNeg, `p10-99`);
@@ -750,8 +750,8 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
HANDLER_WRITE 10
# + 23 write (18 internal I_S + 5 rows)
UNLOCK TABLES;
@@ -759,8 +759,8 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
-HANDLER_READ_RND_NEXT 54
-HANDLER_TMP_WRITE 75
+HANDLER_READ_RND_NEXT 56
+HANDLER_TMP_WRITE 78
HANDLER_WRITE 10
# + 9 locks
#
@@ -773,7 +773,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_RND_NEXT 2
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 2
# 1 commit
# 4 lock (1 ha_partition + 1 ha_innobase) x 2 (lock + unlock)
@@ -791,7 +791,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_KEY 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 2
# 1 commit
# 4 lock
@@ -806,7 +806,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_KEY 1
HANDLER_READ_RND 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 2
# 1 commit
# 4 lock
@@ -819,7 +819,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Nothing, since impossible PARTITION+WHERE clause.
FLUSH STATUS;
UPDATE t1 PARTITION(subp0) SET a = -2, b = concat(b, ', Updated from a = 100')
@@ -828,7 +828,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Nothing, since impossible PARTITION+WHERE clause.
FLUSH STATUS;
UPDATE t1 PARTITION(`p100-99999`) SET a = -2, b = concat(b, ', Updated from a = 100')
@@ -840,7 +840,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_READ_KEY 1
HANDLER_READ_RND 1
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 1
# 6 lock
# 4 read key (1 index init + 1 index read + 1 rnd init + 1 rnd pos)
@@ -856,7 +856,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_READ_KEY 1
HANDLER_READ_RND 1
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 1
HANDLER_WRITE 1
# 10 locks
@@ -874,7 +874,7 @@ HANDLER_COMMIT 1
HANDLER_DELETE 1
HANDLER_READ_KEY 1
HANDLER_READ_RND 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_UPDATE 1
HANDLER_WRITE 1
# 1 commit
@@ -902,7 +902,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Nothing (no matching partition found)
FLUSH STATUS;
UPDATE t1 PARTITION (pNeg) SET b = concat(b, ', Updated2') WHERE a = 1000000;
@@ -910,7 +910,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Nothing (no matching partition found)
FLUSH STATUS;
LOCK TABLE t1 WRITE;
@@ -918,7 +918,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 9 locks
UPDATE t1 PARTITION (subp7) SET b = concat(b, ', Updated to 103'), a = 103 WHERE a = 101;
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -927,8 +927,8 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
HANDLER_READ_KEY 1
HANDLER_READ_RND 1
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
HANDLER_UPDATE 2
# + 4 read key
# + 1 read rnd
@@ -941,8 +941,8 @@ HANDLER_COMMIT 3
HANDLER_DELETE 1
HANDLER_READ_KEY 2
HANDLER_READ_RND 2
-HANDLER_READ_RND_NEXT 54
-HANDLER_TMP_WRITE 75
+HANDLER_READ_RND_NEXT 56
+HANDLER_TMP_WRITE 78
HANDLER_UPDATE 3
HANDLER_WRITE 1
# + 1 delete
@@ -957,8 +957,8 @@ HANDLER_COMMIT 3
HANDLER_DELETE 1
HANDLER_READ_KEY 2
HANDLER_READ_RND 2
-HANDLER_READ_RND_NEXT 81
-HANDLER_TMP_WRITE 101
+HANDLER_READ_RND_NEXT 84
+HANDLER_TMP_WRITE 105
HANDLER_UPDATE 3
HANDLER_WRITE 1
+ 9 locks
@@ -986,7 +986,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_DELETE 2
HANDLER_READ_KEY 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 1 delete
# 4 locks (pruning works!).
# 1 read key (index read)
@@ -998,7 +998,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_DELETE 2
HANDLER_READ_RND_NEXT 3
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 1 delete
# 4 locks
# 1 read first
@@ -1010,7 +1010,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 9 locks
DELETE FROM t1 PARTITION (subp1) WHERE b = 'p0-9:subp3';
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -1018,8 +1018,8 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 2
HANDLER_READ_KEY 1
-HANDLER_READ_RND_NEXT 27
-HANDLER_TMP_WRITE 49
+HANDLER_READ_RND_NEXT 28
+HANDLER_TMP_WRITE 51
# + 3 read key (1 innodb_get_index in records_in_range
# + 1 innobase_get_index in index_init + 1 index read)
DELETE FROM t1 PARTITION (`p0-9`) WHERE b = 'p0-9:subp3';
@@ -1030,8 +1030,8 @@ HANDLER_COMMIT 3
HANDLER_DELETE 2
HANDLER_READ_KEY 3
HANDLER_READ_NEXT 1
-HANDLER_READ_RND_NEXT 54
-HANDLER_TMP_WRITE 75
+HANDLER_READ_RND_NEXT 56
+HANDLER_TMP_WRITE 78
# + 1 delete
# + 6 read key (same as above, but for two subpartitions)
# + 1 read next (read next after found row)
@@ -1043,8 +1043,8 @@ HANDLER_COMMIT 3
HANDLER_DELETE 2
HANDLER_READ_KEY 3
HANDLER_READ_NEXT 1
-HANDLER_READ_RND_NEXT 81
-HANDLER_TMP_WRITE 101
+HANDLER_READ_RND_NEXT 84
+HANDLER_TMP_WRITE 105
# + 9 locks
# Test multi-table DELETE
# Can be expressed in two different ways.
@@ -1057,7 +1057,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 5
HANDLER_READ_NEXT 5
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 10
# 24 locks (2 table, 5 + 5 subpartitions lock/unlock)
FLUSH STATUS;
@@ -1066,7 +1066,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 14 locks (1 table, 6 subpartitions lock/unlock)
FLUSH STATUS;
INSERT INTO t2 PARTITION (subp3) SELECT * FROM t1 PARTITION (subp3, `p10-99`, `p100-99999`);
@@ -1076,7 +1076,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_READ_FIRST 5
HANDLER_ROLLBACK 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 1
# 16 locks (2 tables, 1 + 5 subpartitions lock/unlock)
FLUSH STATUS;
@@ -1091,7 +1091,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 5
HANDLER_READ_NEXT 5
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 7
# 16 locks (2 tables, 1 + 5 subpartitions lock/unlock)
TRUNCATE TABLE t2;
@@ -1103,7 +1103,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 5
HANDLER_READ_NEXT 5
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 10
# 30 locks (2 table, 8 + 5 subpartitions lock/unlock)
FLUSH STATUS;
@@ -1114,7 +1114,7 @@ VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_FIRST 5
HANDLER_READ_NEXT 7
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
HANDLER_WRITE 7
# 14 locks (2 table, 5 subpartitions lock/unlock)
SHOW CREATE TABLE t1;
@@ -1201,7 +1201,7 @@ WHERE t1.a = t3.a AND t3.b = 'subp3'' at line 1
SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# Multi table delete without any matching rows
FLUSH STATUS;
DELETE t1, t2 FROM t1 PARTITION (pNeg), t3, t2 PARTITION (subp3)
@@ -1211,7 +1211,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
HANDLER_READ_RND_NEXT 3
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 12 locks (3 in t1, 1 in t3, 2 in t2) x 2 (lock + unlock)
# 1 read first (first rnd_next in t2)
# 4 read key (1 innodb_get_index in rnd_init in t2 + index read in t2
@@ -1231,7 +1231,7 @@ HANDLER_READ_KEY 2
HANDLER_READ_NEXT 2
HANDLER_READ_RND 4
HANDLER_READ_RND_NEXT 16
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 4 delete (2 in t2 + 2 in t3)
# 12 locks (3 in t2, 1 in t3, 2 in t1) x 2 (lock + unlock)
# 3 read first (1 in t1 + 1 in t3 + 1 in t3, for second row in t1)
@@ -1279,7 +1279,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
VARIABLE_NAME VARIABLE_VALUE
HANDLER_COMMIT 1
-HANDLER_TMP_WRITE 23
+HANDLER_TMP_WRITE 24
# 6 locks (lock/unlock two subpartitions + table)
# Test on non partitioned table
SELECT * FROM t3 PARTITION (pNeg);
diff --git a/mysql-test/r/profiling.result b/mysql-test/r/profiling.result
index 4c531a8a5f7..32e7e0ddc9d 100644
--- a/mysql-test/r/profiling.result
+++ b/mysql-test/r/profiling.result
@@ -415,7 +415,7 @@ select @@profiling;
drop table if exists t1, t2, t3;
drop view if exists v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
drop function if exists f1;
set session profiling = OFF;
set global profiling_history_size= @start_value;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 40746d2e6c6..567be0d0d3f 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -4144,13 +4144,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref idx idx 6 const 1 100.00 Using index condition
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`c` = 'foo'
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`c` = 'foo'
execute stmt1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref idx idx 6 const 1 100.00 Using index condition
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`c` = 'foo'
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`c` = 'foo'
deallocate prepare stmt1;
prepare stmt1 from
"select * from t1 where (1, 2) in ( select 3, 4 ) or c = 'foo'";
@@ -4193,13 +4193,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0
execute stmt2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0
deallocate prepare stmt2;
drop table t1;
# End of 5.5 tests
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 127fb4c7124..3906875da92 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -1932,26 +1932,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@@ -1979,26 +1979,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -2029,26 +2029,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2069,26 +2069,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2117,26 +2117,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2161,26 +2161,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2207,26 +2207,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2245,26 +2245,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index d341323b0b2..9f5c8956dd8 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -1915,26 +1915,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@@ -1962,26 +1962,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -2012,26 +2012,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2052,26 +2052,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2100,26 +2100,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2144,26 +2144,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2190,26 +2190,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2228,26 +2228,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index ea3cf21e804..46b4d9c58e5 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -1916,26 +1916,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 0 39 8
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 0 39 8
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 0 39 8
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 0 39 8
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 0 39 8
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 0 39 8
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 0 39 8
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 0 39 8
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@@ -1963,26 +1963,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 0 39 8
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 0 39 8
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 0 39 8
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 0 39 8
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 0 39 8
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 0 39 8
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 0 39 8
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 0 39 8
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -2013,26 +2013,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 0 39 8
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 0 39 8
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 0 39 8
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 0 39 8
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 0 39 8
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 0 39 8
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 0 39 8
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 0 39 8
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2053,26 +2053,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 0 39 8
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 0 39 8
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 0 39 8
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 0 39 8
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 0 39 8
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 0 39 8
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 0 39 8
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 0 39 8
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2101,26 +2101,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 0 39 8
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 0 39 8
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 0 39 8
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 0 39 8
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 0 39 8
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 0 39 8
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 0 39 8
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 0 39 8
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2145,26 +2145,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 0 39 8
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 0 39 8
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 0 39 8
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 0 39 8
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 0 39 8
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 0 39 8
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 0 39 8
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 0 39 8
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2191,26 +2191,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 0 39 8
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 0 39 8
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 0 39 8
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 0 39 8
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 0 39 8
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 0 39 8
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 0 39 8
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 0 39 8
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2229,26 +2229,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 0 39 8
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 0 39 8
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 0 39 8
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 0 39 8
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 0 39 8
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 0 39 8
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 0 39 8
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 0 39 8
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 4c4aaa325aa..cc2f0f88b2a 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -1853,26 +1853,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@@ -1900,26 +1900,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -1950,26 +1950,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -1990,26 +1990,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2038,26 +2038,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2082,26 +2082,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2128,26 +2128,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2166,26 +2166,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
@@ -5221,26 +5221,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@@ -5268,26 +5268,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -5318,26 +5318,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -5358,26 +5358,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -5406,26 +5406,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -5450,26 +5450,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -5496,26 +5496,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -5534,26 +5534,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 28f5cf635d0..735a0069ba0 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -2581,7 +2581,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 12,
"filtered": 100,
- "attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1"
+ "attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1"
}
}
}
@@ -2666,7 +2666,7 @@ EXPLAIN
"used_key_parts": ["e"],
"rows": 6,
"filtered": 100,
- "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1 and t2.d is not null"
+ "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1 and t2.d is not null"
},
"table": {
"table_name": "t1",
@@ -2716,7 +2716,7 @@ EXPLAIN
"rows": 5,
"filtered": 100,
"index_condition": "t2.d is not null",
- "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1"
+ "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1"
},
"table": {
"table_name": "t1",
@@ -2776,7 +2776,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "(t1.a,t2.e) in ((4,t1.a + 1),(7,t1.a + 1),(8,t1.a + 1)) and length(t2.f) = 1"
+ "attached_condition": "(t1.a,t2.e) in ((4,t1.a + 1),(7,t1.a + 1),(8,t1.a + 1)) and octet_length(t2.f) = 1"
}
}
}
@@ -2830,7 +2830,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "(t1.a,t2.e) in ((t2.e,t1.a + 1),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1"
+ "attached_condition": "(t1.a,t2.e) in ((t2.e,t1.a + 1),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1"
}
}
}
@@ -2870,7 +2870,7 @@ EXPLAIN
"rows": 13,
"filtered": 100,
"index_condition": "t1.a is not null",
- "attached_condition": "(t1.a,2) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and length(t1.c) = 1"
+ "attached_condition": "(t1.a,2) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and octet_length(t1.c) = 1"
},
"table": {
"table_name": "t2",
@@ -2882,7 +2882,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "length(t2.f) = 1"
+ "attached_condition": "octet_length(t2.f) = 1"
}
}
}
@@ -2958,7 +2958,7 @@ EXPLAIN
"rows": 13,
"filtered": 100,
"index_condition": "t1.a is not null",
- "attached_condition": "(t1.a,1 + 1) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and length(t1.c) = 1"
+ "attached_condition": "(t1.a,1 + 1) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and octet_length(t1.c) = 1"
},
"table": {
"table_name": "t2",
@@ -2970,7 +2970,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "length(t2.f) = 1"
+ "attached_condition": "octet_length(t2.f) = 1"
}
}
}
diff --git a/mysql-test/r/range_mrr_icp.result b/mysql-test/r/range_mrr_icp.result
index f2860aaab76..afce3c66c21 100644
--- a/mysql-test/r/range_mrr_icp.result
+++ b/mysql-test/r/range_mrr_icp.result
@@ -2588,7 +2588,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 12,
"filtered": 100,
- "attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1"
+ "attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1"
}
}
}
@@ -2673,7 +2673,7 @@ EXPLAIN
"used_key_parts": ["e"],
"rows": 6,
"filtered": 100,
- "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1 and t2.d is not null",
+ "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1 and t2.d is not null",
"mrr_type": "Rowid-ordered scan"
},
"table": {
@@ -2724,7 +2724,7 @@ EXPLAIN
"rows": 5,
"filtered": 100,
"index_condition": "t2.d is not null",
- "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1",
+ "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1",
"mrr_type": "Rowid-ordered scan"
},
"table": {
@@ -2786,7 +2786,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "(t1.a,t2.e) in ((4,t1.a + 1),(7,t1.a + 1),(8,t1.a + 1)) and length(t2.f) = 1"
+ "attached_condition": "(t1.a,t2.e) in ((4,t1.a + 1),(7,t1.a + 1),(8,t1.a + 1)) and octet_length(t2.f) = 1"
}
}
}
@@ -2840,7 +2840,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "(t1.a,t2.e) in ((t2.e,t1.a + 1),<cache>((7,7)),<cache>((8,8))) and length(t2.f) = 1"
+ "attached_condition": "(t1.a,t2.e) in ((t2.e,t1.a + 1),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1"
}
}
}
@@ -2880,7 +2880,7 @@ EXPLAIN
"rows": 13,
"filtered": 100,
"index_condition": "t1.a is not null",
- "attached_condition": "(t1.a,2) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and length(t1.c) = 1",
+ "attached_condition": "(t1.a,2) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and octet_length(t1.c) = 1",
"mrr_type": "Rowid-ordered scan"
},
"table": {
@@ -2893,7 +2893,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "length(t2.f) = 1"
+ "attached_condition": "octet_length(t2.f) = 1"
}
}
}
@@ -2969,7 +2969,7 @@ EXPLAIN
"rows": 13,
"filtered": 100,
"index_condition": "t1.a is not null",
- "attached_condition": "(t1.a,1 + 1) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and length(t1.c) = 1",
+ "attached_condition": "(t1.a,1 + 1) in (<cache>((2,2)),<cache>((7,7)),<cache>((8,8))) and octet_length(t1.c) = 1",
"mrr_type": "Rowid-ordered scan"
},
"table": {
@@ -2982,7 +2982,7 @@ EXPLAIN
"ref": ["test.t1.a"],
"rows": 3,
"filtered": 100,
- "attached_condition": "length(t2.f) = 1"
+ "attached_condition": "octet_length(t2.f) = 1"
}
}
}
diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result
index 2b8c925b309..ff8566abe02 100644
--- a/mysql-test/r/rename.result
+++ b/mysql-test/r/rename.result
@@ -74,7 +74,7 @@ End of 4.1 tests
create table t1(f1 int);
create view v1 as select * from t1;
alter table v1 rename to v2;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
drop view v1;
drop table t1;
End of 5.0 tests
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 90216c6cedc..5859bd0fae6 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -5263,9 +5263,7 @@ UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
AS foo
;
-coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
-0.0000
-0.0000
+ERROR HY000: Illegal parameter data type geometry for operation 'avg'
CREATE table t1(a text);
INSERT INTO t1 VALUES (''), ('');
SELECT avg(distinct(t1.a)) FROM t1, t1 t2
diff --git a/mysql-test/r/select_jcl6.result b/mysql-test/r/select_jcl6.result
index 054aa94763a..c9d582bb75a 100644
--- a/mysql-test/r/select_jcl6.result
+++ b/mysql-test/r/select_jcl6.result
@@ -5274,9 +5274,7 @@ UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
AS foo
;
-coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
-0.0000
-0.0000
+ERROR HY000: Illegal parameter data type geometry for operation 'avg'
CREATE table t1(a text);
INSERT INTO t1 VALUES (''), ('');
SELECT avg(distinct(t1.a)) FROM t1, t1 t2
diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result
index 90216c6cedc..5859bd0fae6 100644
--- a/mysql-test/r/select_pkeycache.result
+++ b/mysql-test/r/select_pkeycache.result
@@ -5263,9 +5263,7 @@ UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
AS foo
;
-coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
-0.0000
-0.0000
+ERROR HY000: Illegal parameter data type geometry for operation 'avg'
CREATE table t1(a text);
INSERT INTO t1 VALUES (''), ('');
SELECT avg(distinct(t1.a)) FROM t1, t1 t2
diff --git a/mysql-test/r/selectivity.result b/mysql-test/r/selectivity.result
index 64199f983ee..8b447f85013 100644
--- a/mysql-test/r/selectivity.result
+++ b/mysql-test/r/selectivity.result
@@ -80,7 +80,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.part.p_partkey' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`region`.`r_regionkey` = `dbt3_s001`.`nation`.`n_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`region`.`r_regionkey` = `dbt3_s001`.`nation`.`n_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((/* select#2 */ select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
set optimizer_use_condition_selectivity=4;
explain extended
select
@@ -121,7 +121,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.part.p_partkey' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((/* select#2 */ select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
=== Q15 ===
create view revenue0 (supplier_no, total_revenue) as
select l_suppkey, sum(l_extendedprice * (1 - l_discount))
@@ -145,7 +145,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY <derived4> ALL NULL NULL NULL NULL 268 100.00
4 DERIVED lineitem range i_l_shipdate i_l_shipdate 4 NULL 268 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (/* select#2 */ select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
select s_suppkey, s_name, s_address, s_phone, total_revenue
from supplier, revenue0
where s_suppkey = supplier_no
@@ -166,7 +166,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY <derived4> ALL NULL NULL NULL NULL 268 100.00
4 DERIVED lineitem range i_l_shipdate i_l_shipdate 4 NULL 268 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (/* select#2 */ select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
select s_suppkey, s_name, s_address, s_phone, total_revenue
from supplier, revenue0
where s_suppkey = supplier_no
@@ -193,7 +193,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY partsupp ref PRIMARY,i_ps_partkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where; Using index
2 MATERIALIZED supplier ALL PRIMARY NULL NULL NULL 10 100.00 Using where
Warnings:
-Note 1003 select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
+Note 1003 /* select#1 */ select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (/* select#2 */ select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
@@ -237,7 +237,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY partsupp ref PRIMARY,i_ps_partkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where; Using index
2 MATERIALIZED supplier ALL PRIMARY NULL NULL NULL 10 100.00 Using where
Warnings:
-Note 1003 select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
+Note 1003 /* select#1 */ select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (/* select#2 */ select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
@@ -281,7 +281,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY partsupp ref PRIMARY,i_ps_partkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where; Using index
2 MATERIALIZED supplier ALL PRIMARY NULL NULL NULL 10 100.00 Using where
Warnings:
-Note 1003 select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
+Note 1003 /* select#1 */ select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (/* select#2 */ select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
@@ -328,7 +328,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY lineitem ref PRIMARY,i_l_orderkey,i_l_orderkey_quantity i_l_orderkey_quantity 4 dbt3_s001.orders.o_orderkey 4 100.00 Using index
2 MATERIALIZED lineitem index NULL i_l_orderkey_quantity 13 NULL 6005 100.00 Using index
Warnings:
-Note 1003 select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `<subquery2>`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
+Note 1003 /* select#1 */ select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (/* select#2 */ select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `<subquery2>`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
select
c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
from customer, orders, lineitem
@@ -362,7 +362,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY lineitem ref PRIMARY,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 <subquery2>.l_orderkey 4 100.00
2 MATERIALIZED lineitem index NULL i_l_orderkey_quantity 13 NULL 6005 100.00 Using index
Warnings:
-Note 1003 select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `dbt3_s001`.`orders`.`o_orderkey` = `<subquery2>`.`l_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `<subquery2>`.`l_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
+Note 1003 /* select#1 */ select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (/* select#2 */ select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `dbt3_s001`.`orders`.`o_orderkey` = `<subquery2>`.`l_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `<subquery2>`.`l_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
select
c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
from customer, orders, lineitem
@@ -400,7 +400,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
+Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
from (
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
@@ -441,7 +441,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 91.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
+Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
from (
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
@@ -491,7 +491,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -544,7 +544,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -599,7 +599,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -654,7 +654,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -709,7 +709,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_suppkey` = `dbt3_s001`.`supplier`.`s_suppkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -985,7 +985,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 14 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where <cache>(<in_optimizer>(1,exists(select 1 from `test`.`t1` join `test`.`t2`))) and `test`.`t1`.`a` <> `test`.`t2`.`b` or `test`.`t1`.`a` <= 4
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where <cache>(<in_optimizer>(1,exists(/* select#2 */ select 1 from `test`.`t1` join `test`.`t2`))) and `test`.`t1`.`a` <> `test`.`t2`.`b` or `test`.`t1`.`a` <= 4
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result
index a05c14c8e71..8128edb2901 100644
--- a/mysql-test/r/selectivity_innodb.result
+++ b/mysql-test/r/selectivity_innodb.result
@@ -83,7 +83,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.part.p_partkey' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((/* select#2 */ select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
set optimizer_use_condition_selectivity=4;
explain extended
select
@@ -124,7 +124,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.part.p_partkey' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_acctbal` AS `s_acctbal`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`nation`.`n_name` AS `n_name`,`dbt3_s001`.`part`.`p_partkey` AS `p_partkey`,`dbt3_s001`.`part`.`p_mfgr` AS `p_mfgr`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`dbt3_s001`.`supplier`.`s_comment` AS `s_comment` from `dbt3_s001`.`part` join `dbt3_s001`.`supplier` join `dbt3_s001`.`partsupp` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`part`.`p_size` = 9 and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_type` like '%TIN' and `dbt3_s001`.`partsupp`.`ps_supplycost` = <expr_cache><`dbt3_s001`.`part`.`p_partkey`>((/* select#2 */ select min(`dbt3_s001`.`partsupp`.`ps_supplycost`) from `dbt3_s001`.`partsupp` join `dbt3_s001`.`supplier` join `dbt3_s001`.`nation` join `dbt3_s001`.`region` where `dbt3_s001`.`supplier`.`s_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_regionkey` = `dbt3_s001`.`region`.`r_regionkey` and `dbt3_s001`.`region`.`r_name` = 'ASIA' and `dbt3_s001`.`part`.`p_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`)) order by `dbt3_s001`.`supplier`.`s_acctbal` desc,`dbt3_s001`.`nation`.`n_name`,`dbt3_s001`.`supplier`.`s_name`,`dbt3_s001`.`part`.`p_partkey`
=== Q15 ===
create view revenue0 (supplier_no, total_revenue) as
select l_suppkey, sum(l_extendedprice * (1 - l_discount))
@@ -148,7 +148,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY <derived4> ALL NULL NULL NULL NULL 229 100.00
4 DERIVED lineitem range i_l_shipdate i_l_shipdate 4 NULL 229 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (/* select#2 */ select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
select s_suppkey, s_name, s_address, s_phone, total_revenue
from supplier, revenue0
where s_suppkey = supplier_no
@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY <derived4> ALL NULL NULL NULL NULL 228 100.00
4 DERIVED lineitem range i_l_shipdate i_l_shipdate 4 NULL 229 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
+Note 1003 /* select#1 */ select `dbt3_s001`.`supplier`.`s_suppkey` AS `s_suppkey`,`dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address`,`dbt3_s001`.`supplier`.`s_phone` AS `s_phone`,`revenue0`.`total_revenue` AS `total_revenue` from `dbt3_s001`.`supplier` join `dbt3_s001`.`revenue0` where `revenue0`.`supplier_no` = `dbt3_s001`.`supplier`.`s_suppkey` and `revenue0`.`total_revenue` = (/* select#2 */ select max(`revenue0`.`total_revenue`) from `dbt3_s001`.`revenue0`) order by `dbt3_s001`.`supplier`.`s_suppkey`
select s_suppkey, s_name, s_address, s_phone, total_revenue
from supplier, revenue0
where s_suppkey = supplier_no
@@ -196,7 +196,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY partsupp ref PRIMARY,i_ps_partkey i_ps_partkey 4 dbt3_s001.part.p_partkey 3 100.00 Using where; Using index
2 MATERIALIZED supplier ALL PRIMARY NULL NULL NULL 10 100.00 Using where
Warnings:
-Note 1003 select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
+Note 1003 /* select#1 */ select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (/* select#2 */ select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
@@ -240,7 +240,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY partsupp ref PRIMARY,i_ps_partkey i_ps_partkey 4 dbt3_s001.part.p_partkey 3 100.00 Using where; Using index
2 MATERIALIZED supplier ALL PRIMARY NULL NULL NULL 10 100.00 Using where
Warnings:
-Note 1003 select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
+Note 1003 /* select#1 */ select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (/* select#2 */ select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
@@ -284,7 +284,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY partsupp ref PRIMARY,i_ps_partkey i_ps_partkey 4 dbt3_s001.part.p_partkey 3 100.00 Using where; Using index
2 MATERIALIZED supplier ALL PRIMARY NULL NULL NULL 10 100.00 Using where
Warnings:
-Note 1003 select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
+Note 1003 /* select#1 */ select `dbt3_s001`.`part`.`p_brand` AS `p_brand`,`dbt3_s001`.`part`.`p_type` AS `p_type`,`dbt3_s001`.`part`.`p_size` AS `p_size`,count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) AS `supplier_cnt` from `dbt3_s001`.`partsupp` join `dbt3_s001`.`part` where `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`part`.`p_brand` <> 'Brand#11' and `dbt3_s001`.`part`.`p_type` not like 'SMALL POLISHED%' and `dbt3_s001`.`part`.`p_size` in (49,37,27,5,40,6,22,8) and !<expr_cache><`dbt3_s001`.`partsupp`.`ps_suppkey`>(<in_optimizer>(`dbt3_s001`.`partsupp`.`ps_suppkey`,`dbt3_s001`.`partsupp`.`ps_suppkey` in ( <materialize> (/* select#2 */ select `dbt3_s001`.`supplier`.`s_suppkey` from `dbt3_s001`.`supplier` where `dbt3_s001`.`supplier`.`s_comment` like '%Customer%Complaints%' ), <primary_index_lookup>(`dbt3_s001`.`partsupp`.`ps_suppkey` in <temporary table> on distinct_key where `dbt3_s001`.`partsupp`.`ps_suppkey` = `<subquery2>`.`s_suppkey`)))) group by `dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size` order by count(distinct `dbt3_s001`.`partsupp`.`ps_suppkey`) desc,`dbt3_s001`.`part`.`p_brand`,`dbt3_s001`.`part`.`p_type`,`dbt3_s001`.`part`.`p_size`
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
@@ -331,7 +331,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY lineitem ref PRIMARY,i_l_orderkey,i_l_orderkey_quantity i_l_orderkey_quantity 4 dbt3_s001.orders.o_orderkey 4 100.00 Using index
2 MATERIALIZED lineitem index NULL PRIMARY 8 NULL 6005 100.00
Warnings:
-Note 1003 select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `<subquery2>`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
+Note 1003 /* select#1 */ select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (/* select#2 */ select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `<subquery2>`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `dbt3_s001`.`orders`.`o_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
select
c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
from customer, orders, lineitem
@@ -365,7 +365,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY lineitem ref PRIMARY,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 <subquery2>.l_orderkey 4 100.00
2 MATERIALIZED lineitem index NULL PRIMARY 8 NULL 6005 100.00
Warnings:
-Note 1003 select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `dbt3_s001`.`orders`.`o_orderkey` = `<subquery2>`.`l_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `<subquery2>`.`l_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
+Note 1003 /* select#1 */ select `dbt3_s001`.`customer`.`c_name` AS `c_name`,`dbt3_s001`.`customer`.`c_custkey` AS `c_custkey`,`dbt3_s001`.`orders`.`o_orderkey` AS `o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE` AS `o_orderdate`,`dbt3_s001`.`orders`.`o_totalprice` AS `o_totalprice`,sum(`dbt3_s001`.`lineitem`.`l_quantity`) AS `sum(l_quantity)` from <materialize> (/* select#2 */ select `dbt3_s001`.`lineitem`.`l_orderkey` from `dbt3_s001`.`lineitem` group by `dbt3_s001`.`lineitem`.`l_orderkey` having sum(`dbt3_s001`.`lineitem`.`l_quantity`) > 250) join `dbt3_s001`.`customer` join `dbt3_s001`.`orders` join `dbt3_s001`.`lineitem` where `dbt3_s001`.`customer`.`c_custkey` = `dbt3_s001`.`orders`.`o_custkey` and `dbt3_s001`.`orders`.`o_orderkey` = `<subquery2>`.`l_orderkey` and `dbt3_s001`.`lineitem`.`l_orderkey` = `<subquery2>`.`l_orderkey` group by `dbt3_s001`.`customer`.`c_name`,`dbt3_s001`.`customer`.`c_custkey`,`dbt3_s001`.`orders`.`o_orderkey`,`dbt3_s001`.`orders`.`o_orderDATE`,`dbt3_s001`.`orders`.`o_totalprice` order by `dbt3_s001`.`orders`.`o_totalprice` desc,`dbt3_s001`.`orders`.`o_orderDATE`
select
c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
from customer, orders, lineitem
@@ -403,7 +403,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
+Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
from (
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
@@ -444,7 +444,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 SUBQUERY customer ALL NULL NULL NULL NULL 150 91.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.customer.c_custkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
+Note 1003 /* select#1 */ select substr(`dbt3_s001`.`customer`.`c_phone`,1,2) AS `cntrycode`,count(0) AS `numcust`,sum(`dbt3_s001`.`customer`.`c_acctbal`) AS `totacctbal` from `dbt3_s001`.`customer` where substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25') and `dbt3_s001`.`customer`.`c_acctbal` > (/* select#3 */ select avg(`dbt3_s001`.`customer`.`c_acctbal`) from `dbt3_s001`.`customer` where `dbt3_s001`.`customer`.`c_acctbal` > 0.00 and substr(`dbt3_s001`.`customer`.`c_phone`,1,2) in ('10','20','14','19','11','28','25')) and !<in_optimizer>(1,exists(/* select#4 */ select 1 from `dbt3_s001`.`orders` where `dbt3_s001`.`orders`.`o_custkey` = `dbt3_s001`.`customer`.`c_custkey`)) group by substr(`dbt3_s001`.`customer`.`c_phone`,1,2) order by substr(`dbt3_s001`.`customer`.`c_phone`,1,2)
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
from (
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
@@ -494,7 +494,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -548,7 +548,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -604,7 +604,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -660,7 +660,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -716,7 +716,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
-Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
+Note 1003 /* select#1 */ select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where `dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey` and `dbt3_s001`.`nation`.`n_name` = 'UNITED STATES' and `dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey` and `dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((/* select#4 */ select 0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`) from `dbt3_s001`.`lineitem` where `dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey` and `dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey` and `dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date)) and `dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>(cast('1993-01-01' as date) + interval '1' year))) and `dbt3_s001`.`part`.`p_name` like 'g%' order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
@@ -995,7 +995,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t2 ALL NULL NULL NULL NULL 7 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 14 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where <cache>(<in_optimizer>(1,exists(select 1 from `test`.`t1` join `test`.`t2`))) and `test`.`t1`.`a` <> `test`.`t2`.`b` or `test`.`t1`.`a` <= 4
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where <cache>(<in_optimizer>(1,exists(/* select#2 */ select 1 from `test`.`t1` join `test`.`t2`))) and `test`.`t1`.`a` <> `test`.`t2`.`b` or `test`.`t1`.`a` <= 4
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
diff --git a/mysql-test/r/signal.result b/mysql-test/r/signal.result
index f05e357104d..4c2dda51a2f 100644
--- a/mysql-test/r/signal.result
+++ b/mysql-test/r/signal.result
@@ -1715,6 +1715,7 @@ show warnings $$
Level Code Message
Warning 1012 Raising a warning
Error 5555 RESIGNAL to not found
+Note 4070 At line 9 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1739,6 +1740,7 @@ show warnings $$
Level Code Message
Warning 1012 Raising a warning
Error 5555 RESIGNAL to error
+Note 4070 At line 9 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1787,6 +1789,7 @@ show warnings $$
Level Code Message
Error 1012 Raising a not found
Error 5555 RESIGNAL to not found
+Note 4070 At line 9 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1811,6 +1814,7 @@ show warnings $$
Level Code Message
Error 1012 Raising a not found
Error 5555 RESIGNAL to error
+Note 4070 At line 9 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1859,6 +1863,7 @@ show warnings $$
Level Code Message
Error 1012 Raising an error
Error 5555 RESIGNAL to not found
+Note 4070 At line 9 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1883,6 +1888,7 @@ show warnings $$
Level Code Message
Error 1012 Raising an error
Error 5555 RESIGNAL to error
+Note 4070 At line 9 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1925,6 +1931,7 @@ show warnings $$
Level Code Message
Warning 1264 Out of range value for column 'a' at row 1
Error 5555 RESIGNAL to a not found
+Note 4070 At line 8 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1946,6 +1953,7 @@ show warnings $$
Level Code Message
Warning 1264 Out of range value for column 'a' at row 1
Error 5555 RESIGNAL to an error
+Note 4070 At line 8 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1996,6 +2004,7 @@ show warnings $$
Level Code Message
Error 1329 No data - zero rows fetched, selected, or processed
Error 5555 RESIGNAL to a not found
+Note 4070 At line 10 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -2021,6 +2030,7 @@ show warnings $$
Level Code Message
Error 1329 No data - zero rows fetched, selected, or processed
Error 5555 RESIGNAL to an error
+Note 4070 At line 10 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -2063,6 +2073,7 @@ show warnings $$
Level Code Message
Error 1051 Unknown table 'test.no_such_table'
Error 5555 RESIGNAL to a not found
+Note 4070 At line 8 in test.test_resignal
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -2084,6 +2095,7 @@ show warnings $$
Level Code Message
Error 1051 Unknown table 'test.no_such_table'
Error 5555 RESIGNAL to an error
+Note 4070 At line 8 in test.test_resignal
drop procedure test_resignal $$
#
# More complex cases
@@ -2130,6 +2142,7 @@ ERROR 42000: Hi, I am a useless error message
show warnings $$
Level Code Message
Error 9999 Hi, I am a useless error message
+Note 4070 At line 7 in test.peter_p2
drop procedure peter_p1 $$
drop procedure peter_p2 $$
CREATE PROCEDURE peter_p1 ()
@@ -2185,13 +2198,16 @@ Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1232 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Variable 'sql_mode' can't be set to the value of 'NULL'
+Note 4070 At line 8 in test.peter_p1
ERROR 42000: Hi, I am a useless error message
show warnings $$
Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1232 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Variable 'sql_mode' can't be set to the value of 'NULL'
+Note 4070 At line 8 in test.peter_p1
Error 9999 Hi, I am a useless error message
+Note 4070 At line 10 in test.peter_p2
drop procedure peter_p1 $$
drop procedure peter_p2 $$
drop procedure if exists peter_p3 $$
@@ -2209,6 +2225,7 @@ show warnings $$
Level Code Message
Error 1 Original
Error 2 Original
+Note 4070 At line 4 in test.peter_p3
drop procedure peter_p3 $$
drop table t_warn;
drop table t_cursor;
diff --git a/mysql-test/r/signal_code.result b/mysql-test/r/signal_code.result
index ca46f1d2079..32192251fe9 100644
--- a/mysql-test/r/signal_code.result
+++ b/mysql-test/r/signal_code.result
@@ -31,5 +31,5 @@ Pos Instruction
1 stmt 130 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
2 stmt 131 "RESIGNAL foo"
3 stmt 131 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
-4 freturn 3 0
+4 freturn int 0
drop function signal_func;
diff --git a/mysql-test/r/signal_demo3.result b/mysql-test/r/signal_demo3.result
index cc7042269bb..122a2178035 100644
--- a/mysql-test/r/signal_demo3.result
+++ b/mysql-test/r/signal_demo3.result
@@ -79,14 +79,23 @@ show warnings;
Level Code Message
Error 1051 Unknown table 'demo.oops_it_is_not_here'
Error 1644 Oops in proc_9
+Note 4070 At line 4 in demo.proc_9
Error 1644 Oops in proc_8
+Note 4070 At line 4 in demo.proc_8
Error 1644 Oops in proc_7
+Note 4070 At line 4 in demo.proc_7
Error 1644 Oops in proc_6
+Note 4070 At line 4 in demo.proc_6
Error 1644 Oops in proc_5
+Note 4070 At line 4 in demo.proc_5
Error 1644 Oops in proc_4
+Note 4070 At line 4 in demo.proc_4
Error 1644 Oops in proc_3
+Note 4070 At line 4 in demo.proc_3
Error 1644 Oops in proc_2
+Note 4070 At line 4 in demo.proc_2
Error 1644 Oops in proc_1
+Note 4070 At line 4 in demo.proc_1
SET @@session.max_error_count = 5;
SELECT @@session.max_error_count;
@@session.max_error_count
@@ -95,11 +104,11 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
-Error 1644 Oops in proc_5
-Error 1644 Oops in proc_4
-Error 1644 Oops in proc_3
+Note 4070 At line 4 in demo.proc_3
Error 1644 Oops in proc_2
+Note 4070 At line 4 in demo.proc_2
Error 1644 Oops in proc_1
+Note 4070 At line 4 in demo.proc_1
SET @@session.max_error_count = 7;
SELECT @@session.max_error_count;
@@session.max_error_count
@@ -108,13 +117,13 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
-Error 1644 Oops in proc_7
-Error 1644 Oops in proc_6
-Error 1644 Oops in proc_5
-Error 1644 Oops in proc_4
+Note 4070 At line 4 in demo.proc_4
Error 1644 Oops in proc_3
+Note 4070 At line 4 in demo.proc_3
Error 1644 Oops in proc_2
+Note 4070 At line 4 in demo.proc_2
Error 1644 Oops in proc_1
+Note 4070 At line 4 in demo.proc_1
SET @@session.max_error_count = 9;
SELECT @@session.max_error_count;
@@session.max_error_count
@@ -123,15 +132,15 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
-Error 1644 Oops in proc_9
-Error 1644 Oops in proc_8
-Error 1644 Oops in proc_7
-Error 1644 Oops in proc_6
-Error 1644 Oops in proc_5
+Note 4070 At line 4 in demo.proc_5
Error 1644 Oops in proc_4
+Note 4070 At line 4 in demo.proc_4
Error 1644 Oops in proc_3
+Note 4070 At line 4 in demo.proc_3
Error 1644 Oops in proc_2
+Note 4070 At line 4 in demo.proc_2
Error 1644 Oops in proc_1
+Note 4070 At line 4 in demo.proc_1
drop database demo;
SET @@global.max_error_count = @start_global_value;
SELECT @@global.max_error_count;
diff --git a/mysql-test/r/sp-anchor-row-type-cursor.result b/mysql-test/r/sp-anchor-row-type-cursor.result
new file mode 100644
index 00000000000..a2435e17f9f
--- /dev/null
+++ b/mysql-test/r/sp-anchor-row-type-cursor.result
@@ -0,0 +1,1003 @@
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+#
+# A complete working example
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE c CURSOR FOR SELECT a,b FROM t1;
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE rec ROW TYPE OF c;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
+OPEN c;
+read_loop: LOOP
+FETCH c INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT rec.a ,rec.b FROM dual;
+INSERT INTO t2 VALUES (rec.a, rec.b);
+END LOOP;
+CLOSE c;
+END;
+END;
+$$
+CALL p1();
+rec.a rec.b
+10 b10
+rec.a rec.b
+20 b20
+rec.a rec.b
+30 b30
+SELECT * FROM t2;
+a b
+10 b10
+20 b20
+30 b30
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# cursor ROW TYPE referring to a table in a non-existing database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM tes2.t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'tes2.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+ERROR 42S02: Table 'tes2.t1' doesn't exist
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# cursor ROW TYPE referring to a table in the current database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+DROP PROCEDURE p1;
+#
+# cursor ROW TYPE referring to a table in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM test.t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Cursor ROW TYPE referring to a view in the current database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM v1;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# cursor ROW TYPE referring to a view in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM test.v1;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Checking that all cursor ROW TYPE fields are NULL by default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b rec1.c rec1.d
+NULL NULL NULL NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A cursor ROW TYPE variable with a ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(10,'bbb');
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A cursor ROW TYPE variable with an incompatible ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(10,'bbb','ccc');
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A cursor ROW TYPE variable with a ROW variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT ROW(10,'bbb');
+DECLARE rec2 ROW TYPE OF cur DEFAULT rec1;
+SELECT rec2.a, rec2.b;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A ROW variable using a cursor ROW TYPE variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(10,'bbb');
+DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+SELECT rec2.a, rec2.b;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning cursor ROW TYPE variables with a different column count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+DECLARE rec2 ROW TYPE OF cur2;
+SET rec2=rec1;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+DECLARE rec2 ROW TYPE OF cur2;
+SET rec1=rec2;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 3 column(s)
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning compatible cursor ROW TYPE variables (equal number of fields)
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+DECLARE rec2 ROW TYPE OF cur2;
+SET rec1.a= 10;
+SET rec1.b= 'bbb';
+SET rec2=rec1;
+SELECT rec2.x, rec2.y;
+END;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between incompatible cursor ROW TYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+DECLARE rec2 ROW(x INT,y INT,z INT);
+SET rec2.x= 10;
+SET rec2.y= 20;
+SET rec2.z= 30;
+SET rec1= rec2;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between compatible cursor ROW TYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+DECLARE rec2 ROW(x INT,y INT);
+SET rec2.x= 10;
+SET rec2.y= 20;
+SET rec1= rec2;
+SELECT rec1.a, rec1.b;
+SET rec1.a= 11;
+SET rec1.b= 21;
+SET rec2= rec1;
+SELECT rec2.x, rec2.y;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+rec2.x rec2.y
+11 21
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning cursor ROW TYPE from a ROW expression
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+SET rec1= ROW(10,20);
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor ROW TYPE variable with a wrong field count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+BEGIN
+DECLARE rec2 ROW TYPE OF cur2;
+OPEN cur1;
+FETCH cur1 INTO rec2;
+CLOSE cur1;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Incorrect number of FETCH variables
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor ROW TYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE rec ROW TYPE OF cur;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN cur;
+read_loop: LOOP
+FETCH cur INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT rec.a, rec.b, rec.c, rec.d;
+INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+END LOOP;
+CLOSE cur;
+END;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d
+10 bb1 11111.1 12.31
+rec.a rec.b rec.c rec.d
+20 bb2 22222.2 12.32
+rec.a rec.b rec.c rec.d
+30 bb3 33333.3 12.33
+SELECT * FROM t2;
+a b c d
+10 bb1 11111.1 12.31
+20 bb2 22222.2 12.32
+30 bb3 33333.3 12.33
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor ROW TYPE variable, ROW TYPE OF cur declared inside the LOOP
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN cur;
+read_loop: LOOP
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+FETCH cur INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT rec.a, rec.b, rec.c, rec.d;
+INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+END;
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d
+10 bb1 11111.1 12.31
+rec.a rec.b rec.c rec.d
+20 bb2 22222.2 12.32
+rec.a rec.b rec.c rec.d
+30 bb3 33333.3 12.33
+SELECT * FROM t2;
+a b c d
+10 bb1 11111.1 12.31
+20 bb2 22222.2 12.32
+30 bb3 33333.3 12.33
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor ROW TYPE variable with different column names
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+BEGIN
+DECLARE rec2 ROW TYPE OF cur2;
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.x, rec2.y;
+CLOSE cur1;
+END;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor ROW TYPE variable, with truncation
+#
+SET sql_mode='';
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+BEGIN
+DECLARE rec2 ROW TYPE OF cur2;
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.a, rec2.b;
+CLOSE cur1;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 11
+Warnings:
+Warning 1265 Data truncated for column 'b' at row 1
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+#
+# cursor ROW TYPE variables are not allowed in LIMIT
+#
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1 DEFAULT (1,2);
+SELECT * FROM t1 LIMIT rec1.a;
+END;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+DROP TABLE t1;
+#
+# cursor ROW TYPE variable fields as OUT parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(OUT a INT,OUT b VARCHAR(10))
+BEGIN
+SET a=10;
+SET b='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+CALL p1(rec1.a, rec1.b);
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire cursor ROW TYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur DEFAULT ROW(10,'bb');
+CALL p1(rec1);
+END;
+END;
+$$
+CALL p2();
+a.a a.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire cursor ROW TYPE variable as an OUT parameter
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(OUT a ROW(a INT, b VARCHAR(10)))
+BEGIN
+SET a= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur;
+CALL p1(rec1);
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Assigning a cursor ROW TYPE field to an OUT parameter
+#
+CREATE PROCEDURE p1 (INOUT res INTEGER)
+BEGIN
+DECLARE a INT DEFAULT 10;
+DECLARE cur1 CURSOR FOR SELECT a FROM DUAL;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SET res=rec1.a;
+END;
+END;
+$$
+CALL p1(@res);
+SELECT @res;
+@res
+10
+SET @res=NULL;
+DROP PROCEDURE p1;
+#
+# Testing Item_splocal_row_field_by_name::print
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur1 DEFAULT ROW(10,'bb');
+EXPLAIN EXTENDED SELECT rec.a, rec.b;
+END;
+END;
+$$
+CALL p1();
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select rec.a@0["a"] AS `rec.a`,rec.b@0["b"] AS `rec.b`
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Run time error in the cursor statement
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT
+10 AS a,
+CONCAT(_latin1'a' COLLATE latin1_bin,
+_latin1'a' COLLATE latin1_swedish_ci) AS b;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SELECT a,b;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation 'concat'
+DROP PROCEDURE p1;
+#
+# Non-existing field
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur1;
+SELECT rec.c;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+ALTER TABLE t1 ADD c INT;
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+rec.c
+NULL
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that field names are case insensitive
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur DEFAULT ROW(10,'bb');
+SELECT rec.A, rec.B;
+END;
+END;
+$$
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that cursor ROW TYPE uses temporary tables vs shadowed real tables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur DEFAULT ROW(10,'bb');
+SELECT rec.A, rec.B;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'A'
+DROP TEMPORARY TABLE t1;
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that the structure of cursor ROW TYPE variables is determined at the DECLARE CURSOR instantiation time
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+BEGIN
+DECLARE rec ROW TYPE OF cur; -- This has a column "c"
+ SET rec.c=10;
+END;
+END;
+$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur; -- This does not have a column "c"
+ DROP TABLE t1;
+CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+SET rec.c=10;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Duplicate field nams in a cursor referenced by cursor ROW TYPE
+#
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT * FROM t1, t2;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+SELECT rec.a;
+SET rec.a=10;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S21: Duplicate column name 'a'
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# Tricky field names a cursor referenced by cursor ROW TYPE
+#
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('a');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur CURSOR FOR SELECT a, CONCAT(a,'a'), CONCAT(a,'ö') FROM t1;
+BEGIN
+DECLARE rec ROW TYPE OF cur;
+OPEN cur;
+FETCH cur INTO rec;
+CLOSE cur;
+SELECT rec.a, rec.`CONCAT(a,'a')`, rec.`CONCAT(a,'ö')`;
+END;
+END;
+$$
+CALL p1();
+rec.a rec.`CONCAT(a,'a')` rec.`CONCAT(a,'ö')`
+a aa aö
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SET NAMES latin1;
+#
+# Using definitions recursively (cursor ROW TYPE variables in another cursor SELECT)
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b1'),(20,'b2'),(30,'b3');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT a,b FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(0,'b0');
+DECLARE cur2 CURSOR FOR SELECT rec1.a AS a, rec1.b AS b FROM t1;
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE rec2 ROW TYPE OF cur2;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN cur2;
+read_loop: LOOP
+FETCH cur2 INTO rec2;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT rec2.a, rec2.b;
+END LOOP;
+CLOSE cur2;
+END;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+0 b0
+rec2.a rec2.b
+0 b0
+rec2.a rec2.b
+0 b0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing queries with auto-generated Items.
+# An instance of Item_func_conv_charset is created during the below SELECT query.
+# We check here that during an implicit cursor OPEN
+# done in sp_instr_cursor_copy_struct::exec_core()
+# all temporary Items are created on a proper memory root and are safely destroyed.
+#
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b VARCHAR(10) CHARACTER SET utf8);
+INSERT INTO t1 VALUES (0xFF, 'a');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT CONCAT(a,b) AS c FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SELECT HEX(rec1.c);
+END;
+END;
+$$
+CALL p1();
+HEX(rec1.c)
+C3BF61
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# SELECT INTO + cursor ROW TYPE variable with a wrong column count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT 10, 'b0', 'c0';
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: The used SELECT statements have a different number of columns
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SELECT INTO + multiple cursor ROW TYPE variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+SELECT * FROM t1 INTO rec1, rec1;
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# SELECT INTO + cursor ROW TYPE working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+#
+# MDEV-12916 Wrong column data type for an INT field of a cursor-anchored ROW variable
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT DEFAULT 10;
+DECLARE cur1 CURSOR FOR SELECT a;
+BEGIN
+DECLARE rec1 ROW TYPE OF cur1;
+CREATE TABLE t1 AS SELECT rec1.a;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+END;
+END;
+$$
+CALL p1();
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `rec1.a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
diff --git a/mysql-test/r/sp-anchor-row-type-table.result b/mysql-test/r/sp-anchor-row-type-table.result
new file mode 100644
index 00000000000..80fc763c4fa
--- /dev/null
+++ b/mysql-test/r/sp-anchor-row-type-table.result
@@ -0,0 +1,681 @@
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+#
+# Referring to a table in a non-existing database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF test2.t1;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test2.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+ERROR 42S02: Table 'test2.t1' doesn't exist
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a table in the current database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF t1;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a table in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF test.t1;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a view in the current database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF v1;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a view in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF test.v1;
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `rec.a` int(11) DEFAULT NULL,
+ `rec.b` varchar(10) DEFAULT NULL,
+ `rec.c` double DEFAULT NULL,
+ `rec.d` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Checking that all table ROW TYPE fields are NULL by default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+END;
+$$
+CALL p1();
+rec1.a rec1.b rec1.c rec1.d
+NULL NULL NULL NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A table ROW TYPE variable with a ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bbb');
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A table ROW TYPE variable with an incompatible ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bbb','ccc');
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A table ROW TYPE variable with a ROW variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT ROW(10,'bbb');
+DECLARE rec2 ROW TYPE OF t1 DEFAULT rec1;
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A ROW variable using a table ROW TYPE variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bbb');
+DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning table ROW TYPE variables with a different column count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+DECLARE rec2 ROW TYPE OF t2;
+SET rec2=rec1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+DECLARE rec2 ROW TYPE OF t2;
+SET rec1=rec2;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 3 column(s)
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning compatible table ROW TYPE variables (equal number of fields)
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+DECLARE rec2 ROW TYPE OF t2;
+SET rec1.a= 10;
+SET rec1.b= 'bbb';
+SET rec2=rec1;
+SELECT rec2.x, rec2.y;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between incompatible table ROW TYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+DECLARE rec2 ROW(x INT,y INT,z INT);
+SET rec2.x= 10;
+SET rec2.y= 20;
+SET rec2.z= 30;
+SET rec1= rec2;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between compatible table ROW TYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+DECLARE rec2 ROW(x INT,y INT);
+SET rec2.x= 10;
+SET rec2.y= 20;
+SET rec1= rec2;
+SELECT rec1.a, rec1.b;
+SET rec1.a= 11;
+SET rec1.b= 21;
+SET rec2= rec1;
+SELECT rec2.x, rec2.y;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+rec2.x rec2.y
+11 21
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning table ROW TYPE from a ROW expression
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+SET rec1= ROW(10,20);
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table ROW TYPE variable with a wrong field count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec2 ROW TYPE OF t2;
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+OPEN cur1;
+FETCH cur1 INTO rec2;
+CLOSE cur1;
+END;
+$$
+CALL p1();
+ERROR HY000: Incorrect number of FETCH variables
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table ROW TYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE rec ROW TYPE OF t1;
+DECLARE cur CURSOR FOR SELECT * FROM t1;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN cur;
+read_loop: LOOP
+FETCH cur INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT rec.a, rec.b, rec.c, rec.d;
+INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d
+10 bb1 11111.1 12.31
+rec.a rec.b rec.c rec.d
+20 bb2 22222.2 12.32
+rec.a rec.b rec.c rec.d
+30 bb3 33333.3 12.33
+SELECT * FROM t2;
+a b c d
+10 bb1 11111.1 12.31
+20 bb2 22222.2 12.32
+30 bb3 33333.3 12.33
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table ROW TYPE variable with different column names
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec2 ROW TYPE OF t2;
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.x, rec2.y;
+CLOSE cur1;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table ROW TYPE variable, with truncation
+#
+SET sql_mode='';
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec2 ROW TYPE OF t2;
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.a, rec2.b;
+CLOSE cur1;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 11
+Warnings:
+Warning 1265 Data truncated for column 'b' at row 1
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+#
+# table ROW TYPE variables are not allowed in LIMIT
+#
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1 DEFAULT (1,2);
+SELECT * FROM t1 LIMIT rec1.a;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+DROP TABLE t1;
+#
+# table ROW TYPE variable fields as OUT parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(OUT a INT,OUT b VARCHAR(10))
+BEGIN
+SET a=10;
+SET b='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+CALL p1(rec1.a, rec1.b);
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire table ROW TYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+CALL p1(rec1);
+END;
+$$
+CALL p2();
+a.a a.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire table ROW TYPE variable as an OUT parameter
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(OUT a ROW(a INT, b VARCHAR(10)))
+BEGIN
+SET a= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+CALL p1(rec1);
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Assigning a table ROW TYPE field to an OUT parameter
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1 (INOUT res INTEGER)
+BEGIN
+DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'b0');
+SET res=rec1.a;
+END;
+$$
+CALL p1(@res);
+SELECT @res;
+@res
+10
+SET @res=NULL;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing Item_splocal_row_field_by_name::print
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+EXPLAIN EXTENDED SELECT rec.a, rec.b;
+END;
+$$
+CALL p1();
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select rec.a@0["a"] AS `rec.a`,rec.b@0["b"] AS `rec.b`
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Non-existing field
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF t1;
+SELECT rec.c;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+ALTER TABLE t1 ADD c INT;
+CALL p1();
+rec.c
+NULL
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that field names are case insensitive
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+SELECT rec.A, rec.B;
+END;
+$$
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that table ROW TYPE uses temporary tables vs shadowed real tables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+SELECT rec.A, rec.B;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'A'
+DROP TEMPORARY TABLE t1;
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that the structure of table ROW TYPE variables is determined at the very beginning and is not changed after ALTER
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+ALTER TABLE t1 ADD c INT;
+BEGIN
+DECLARE rec ROW TYPE OF t1; -- this will not have column "c"
+ SET rec.c=10;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SELECT INTO + table ROW TYPE variable with a wrong column count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+SELECT 10,'a','b' FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: The used SELECT statements have a different number of columns
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SELECT INTO + multiple table ROW TYPE variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+SELECT 10,'a' FROM t1 INTO rec1, rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SELECT INTO + table ROW TYPE working example
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW TYPE OF t1;
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+#
+# MDEV-12347 Valgrind reports invalid read errors in Item_field_row::element_index_by_name
+#
+CREATE TABLE t1 (a INT, b ENUM('b0','b1','b12','b3'));
+CREATE PROCEDURE p1()
+BEGIN
+BEGIN
+DECLARE rec ROW TYPE OF t1;
+SET rec.b='b0';
+SELECT rec.b;
+END;
+END;
+$$
+CALL p1();
+rec.b
+b0
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT, b SET('b0','b1','b12','b3'));
+CREATE PROCEDURE p1()
+BEGIN
+BEGIN
+DECLARE rec ROW TYPE OF t1;
+SET rec.b='b0';
+SELECT rec.b;
+END;
+END;
+$$
+CALL p1();
+rec.b
+b0
+DROP TABLE t1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/r/sp-anchor-type.result b/mysql-test/r/sp-anchor-type.result
new file mode 100644
index 00000000000..44f67531b2f
--- /dev/null
+++ b/mysql-test/r/sp-anchor-type.result
@@ -0,0 +1,967 @@
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+#
+# Missing table
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+DROP PROCEDURE p1;
+#
+# Missing column
+#
+CREATE TABLE t1 (b INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a;
+END;
+$$
+CALL p1();
+ERROR 42S22: Unknown column 'a' in 't1'
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# One TYPE OF variable
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a;
+SET a= 123;
+SELECT a;
+END;
+$$
+CALL p1();
+a
+123
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Two TYPE OF variables, with a truncation warning on assignment
+#
+SET sql_mode='';
+CREATE TABLE t1 (a TINYINT, b INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a;
+DECLARE b TYPE OF t1.b;
+SET a= 200;
+SET b= 200;
+SELECT a, b;
+END;
+$$
+CALL p1();
+a b
+127 200
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# TYPE OF variables for fields with various attributes
+#
+CREATE TABLE t1 (
+id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
+a TINYINT NOT NULL,
+b INT NOT NULL,
+ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+UNIQUE(a)
+);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE id TYPE OF t1.id;
+DECLARE a TYPE OF t1.a;
+DECLARE b TYPE OF t1.b;
+DECLARE ts TYPE OF t1.ts;
+SELECT id, a, b, ts;
+CREATE TABLE t2 AS SELECT id, a, b, ts;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+id a b ts
+NULL NULL NULL NULL
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) DEFAULT NULL,
+ `a` tinyint(4) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `ts` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# TYPE OF + virtual columns
+#
+CREATE TABLE t1 (
+a INT NOT NULL,
+b VARCHAR(32),
+c INT AS (a + 10) VIRTUAL,
+d VARCHAR(5) AS (left(b,5)) PERSISTENT
+);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE c TYPE OF t1.c;
+DECLARE d TYPE OF t1.d;
+SELECT c, d;
+CREATE TABLE t2 AS SELECT c, d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+c d
+NULL NULL
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `c` int(11) DEFAULT NULL,
+ `d` varchar(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# TYPE OF + the ZEROFILL attribute
+#
+CREATE TABLE t1 (
+dz DECIMAL(10,3) ZEROFILL
+);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE dzr TYPE OF t1.dz DEFAULT 10;
+DECLARE dzt DECIMAL(10,3) ZEROFILL DEFAULT 10;
+SELECT dzr, dzt;
+CREATE TABLE t2 AS SELECT dzr,dzt;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+dzr dzt
+0000010.000 0000010.000
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `dzr` decimal(10,3) unsigned DEFAULT NULL,
+ `dzt` decimal(10,3) unsigned DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Temporary tables shadow real tables for TYPE OF purposes
+#
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('t1');
+CREATE TEMPORARY TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a DEFAULT 11;
+CREATE TABLE t2 AS SELECT a;
+END;
+$$
+#
+# Should use INT(11) as TYPE OF, as in the temporary table
+#
+CALL p1();
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+11
+DROP TABLE t2;
+SELECT * FROM t1;
+a
+10
+DROP TEMPORARY TABLE t1;
+SELECT * FROM t1;
+a
+t1
+#
+# Should use VARCHAR(10) as TYPE OF, as in the real table
+#
+CALL p1();
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a
+11
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# "TYPE OF t1.a" searches for "t1" in the current database
+#
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a DEFAULT 11;
+CREATE TABLE test.t2 AS SELECT a;
+END;
+$$
+#
+# This interprets "TYPE OF t1.a" as VARCHAR(10), as in test.t1.a
+#
+USE test;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE test.t2;
+#
+# This interprets "TYPE OF t1.a" as INT, as in test1.t1.a
+#
+USE test1;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE test.t2;
+#
+# Error if there is no an active database
+#
+DROP DATABASE test1;
+CALL test.p1();
+ERROR 3D000: No database selected
+USE test;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# A reference to a table in a non-existing database
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF test1.t1.a;
+CREATE TABLE t1 AS SELECT a;
+END;
+$$
+CALL p1;
+ERROR 42S02: Table 'test1.t1' doesn't exist
+DROP PROCEDURE p1;
+#
+# A reference to a table in a different database
+#
+CREATE TABLE t1(a INT);
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF t1.a;
+DECLARE b TYPE OF test1.t1.a;
+CREATE TABLE t2 AS SELECT a,b;
+END;
+$$
+CALL p1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP DATABASE test1;
+DROP TABLE t1;
+#
+# Using a table before it appears in a TYPE OF declaration + multiple TYPE OF declarations
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 (a,b) VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+INSERT INTO t1 (a,b) VALUES (11, 'b11');
+SELECT * FROM t1;
+BEGIN
+DECLARE va TYPE OF t1.a DEFAULT 30;
+DECLARE vb TYPE OF t1.b DEFAULT 'b30';
+INSERT INTO t1 (a,b) VALUES (12,'b12');
+SELECT * FROM t1;
+INSERT INTO t1 (a,b) VALUES (va, vb);
+SELECT * FROM t1;
+END;
+BEGIN
+DECLARE va TYPE OF t1.a DEFAULT 40;
+DECLARE vb TYPE OF t1.b DEFAULT 'b40';
+INSERT INTO t1 (a,b) VALUES (va,vb);
+SELECT * FROM t1;
+END;
+END;
+$$
+CALL p1;
+a b
+10 b10
+11 b11
+a b
+10 b10
+11 b11
+12 b12
+a b
+10 b10
+11 b11
+12 b12
+30 b30
+a b
+10 b10
+11 b11
+12 b12
+30 b30
+40 b40
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TYPE OF variables + TABLE vs VIEW
+#
+CREATE TABLE t1 (
+bit6 BIT(6),
+bit7 BIT(7),
+bit8 BIT(8),
+i1 TINYINT,
+i2 SMALLINT,
+i3 MEDIUMINT,
+i4 INT,
+i8 BIGINT,
+ff FLOAT,
+fd DOUBLE,
+cc CHAR(10),
+cv VARCHAR(10),
+cvu VARCHAR(10) CHARACTER SET utf8,
+t1 TINYTEXT,
+t2 TEXT,
+t3 MEDIUMTEXT,
+t4 LONGTEXT,
+enum1 ENUM('a','b','c'),
+set1 SET('a','b','c'),
+blob1 TINYBLOB,
+blob2 BLOB,
+blob3 MEDIUMBLOB,
+blob4 LONGBLOB,
+yy YEAR,
+dd DATE,
+tm0 TIME,
+tm3 TIME(3),
+tm6 TIME(6),
+dt0 DATETIME,
+dt3 DATETIME(3),
+dt6 DATETIME(6),
+ts0 TIMESTAMP,
+ts3 TIMESTAMP(3),
+ts6 TIMESTAMP(6),
+dc100 DECIMAL(10,0),
+dc103 DECIMAL(10,3),
+dc209 DECIMAL(20,9)
+);
+CREATE PROCEDURE p1(command enum('create','select'))
+BEGIN
+DECLARE bit6 TYPE OF t1.bit6 DEFAULT 0x30;
+DECLARE bit7 TYPE OF t1.bit7 DEFAULT 0x41;
+DECLARE bit8 TYPE OF t1.bit8 DEFAULT 0x7E;
+DECLARE i1 TYPE OF t1.i1 DEFAULT 11;
+DECLARE i2 TYPE OF t1.i2 DEFAULT 12;
+DECLARE i3 TYPE OF t1.i3 DEFAULT 13;
+DECLARE i4 TYPE OF t1.i4 DEFAULT 14;
+DECLARE i8 TYPE OF t1.i8 DEFAULT 18;
+DECLARE ff TYPE OF t1.ff DEFAULT 21;
+DECLARE fd TYPE OF t1.fd DEFAULT 22;
+DECLARE cc TYPE OF t1.cc DEFAULT 'char';
+DECLARE cv TYPE OF t1.cv DEFAULT 'varchar';
+DECLARE cvu TYPE OF t1.cvu DEFAULT 'varcharu8';
+DECLARE t1 TYPE OF t1.t1 DEFAULT 'text1';
+DECLARE t2 TYPE OF t1.t2 DEFAULT 'text2';
+DECLARE t3 TYPE OF t1.t3 DEFAULT 'text3';
+DECLARE t4 TYPE OF t1.t4 DEFAULT 'text4';
+DECLARE enum1 TYPE OF t1.enum1 DEFAULT 'b';
+DECLARE set1 TYPE OF t1.set1 DEFAULT 'a,c';
+DECLARE blob1 TYPE OF t1.blob1 DEFAULT 'blob1';
+DECLARE blob2 TYPE OF t1.blob2 DEFAULT 'blob2';
+DECLARE blob3 TYPE OF t1.blob3 DEFAULT 'blob3';
+DECLARE blob4 TYPE OF t1.blob4 DEFAULT 'blob4';
+DECLARE yy TYPE OF t1.yy DEFAULT 2001;
+DECLARE dd TYPE OF t1.dd DEFAULT '2001-01-01';
+DECLARE tm0 TYPE OF t1.tm0 DEFAULT '00:00:01';
+DECLARE tm3 TYPE OF t1.tm3 DEFAULT '00:00:03.333';
+DECLARE tm6 TYPE OF t1.tm6 DEFAULT '00:00:06.666666';
+DECLARE dt0 TYPE OF t1.dt0 DEFAULT '2001-01-01 00:00:01';
+DECLARE dt3 TYPE OF t1.dt3 DEFAULT '2001-01-03 00:00:01.333';
+DECLARE dt6 TYPE OF t1.dt6 DEFAULT '2001-01-06 00:00:01.666666';
+DECLARE ts0 TYPE OF t1.ts0 DEFAULT '2002-01-01 00:00:01';
+DECLARE ts3 TYPE OF t1.ts3 DEFAULT '2002-01-03 00:00:01.333';
+DECLARE ts6 TYPE OF t1.ts6 DEFAULT '2002-01-06 00:00:01.666666';
+DECLARE dc100 TYPE OF t1.dc100 DEFAULT 10;
+DECLARE dc103 TYPE OF t1.dc103 DEFAULT 10.123;
+DECLARE dc209 TYPE OF t1.dc209 DEFAULT 10.123456789;
+CASE
+WHEN command='create' THEN
+CREATE TABLE t2 AS SELECT
+bit6, bit7, bit8,
+i1,i2,i3,i4,i8,
+ff,fd, dc100, dc103, dc209,
+cc,cv,cvu,
+t1,t2,t3,t4,
+enum1, set1,
+blob1, blob2, blob3, blob4,
+dd, yy,
+tm0, tm3, tm6,
+dt0, dt3, dt6,
+ts0, ts3, ts6;
+WHEN command='select' THEN
+SELECT
+bit6, bit7, bit8,
+i1,i2,i3,i4,i8,
+ff,fd, dc100, dc103, dc209,
+cc,cv,cvu,
+t1,t2,t3,t4,
+enum1, set1,
+blob1, blob2, blob3, blob4,
+dd, yy,
+tm0, tm3, tm6,
+dt0, dt3, dt6,
+ts0, ts3, ts6;
+END CASE;
+END;
+$$
+#
+# TABLE
+#
+CALL p1('create');
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `bit6` bit(6) DEFAULT NULL,
+ `bit7` bit(7) DEFAULT NULL,
+ `bit8` bit(8) DEFAULT NULL,
+ `i1` tinyint(4) DEFAULT NULL,
+ `i2` smallint(6) DEFAULT NULL,
+ `i3` mediumint(9) DEFAULT NULL,
+ `i4` int(11) DEFAULT NULL,
+ `i8` bigint(20) DEFAULT NULL,
+ `ff` float DEFAULT NULL,
+ `fd` double DEFAULT NULL,
+ `dc100` decimal(10,0) DEFAULT NULL,
+ `dc103` decimal(10,3) DEFAULT NULL,
+ `dc209` decimal(20,9) DEFAULT NULL,
+ `cc` varchar(10) DEFAULT NULL,
+ `cv` varchar(10) DEFAULT NULL,
+ `cvu` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `t1` tinytext DEFAULT NULL,
+ `t2` text DEFAULT NULL,
+ `t3` mediumtext DEFAULT NULL,
+ `t4` longtext DEFAULT NULL,
+ `enum1` varchar(1) DEFAULT NULL,
+ `set1` varchar(5) DEFAULT NULL,
+ `blob1` tinyblob DEFAULT NULL,
+ `blob2` blob DEFAULT NULL,
+ `blob3` mediumblob DEFAULT NULL,
+ `blob4` longblob DEFAULT NULL,
+ `dd` date DEFAULT NULL,
+ `yy` year(4) DEFAULT NULL,
+ `tm0` time DEFAULT NULL,
+ `tm3` time(3) DEFAULT NULL,
+ `tm6` time(6) DEFAULT NULL,
+ `dt0` datetime DEFAULT NULL,
+ `dt3` datetime(3) DEFAULT NULL,
+ `dt6` datetime(6) DEFAULT NULL,
+ `ts0` timestamp NULL DEFAULT NULL,
+ `ts3` timestamp(3) NULL DEFAULT NULL,
+ `ts6` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+DROP TABLE t2;
+CALL p1('select');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def bit6 bit6 16 6 1 Y 32 0 63
+def bit7 bit7 16 7 1 Y 32 0 63
+def bit8 bit8 16 8 1 Y 32 0 63
+def i1 i1 1 4 2 Y 32768 0 63
+def i2 i2 2 6 2 Y 32768 0 63
+def i3 i3 9 9 2 Y 32768 0 63
+def i4 i4 3 11 2 Y 32768 0 63
+def i8 i8 8 20 2 Y 32768 0 63
+def ff ff 4 12 2 Y 32768 31 63
+def fd fd 5 22 2 Y 32768 31 63
+def dc100 dc100 246 11 2 Y 32768 0 63
+def dc103 dc103 246 12 6 Y 32768 3 63
+def dc209 dc209 246 22 12 Y 32768 9 63
+def cc cc 254 10 4 Y 0 0 8
+def cv cv 253 10 7 Y 0 0 8
+def cvu cvu 253 10 9 Y 0 0 8
+def t1 t1 252 255 5 Y 16 0 8
+def t2 t2 252 65535 5 Y 16 0 8
+def t3 t3 252 16777215 5 Y 16 0 8
+def t4 t4 252 4294967295 5 Y 16 0 8
+def enum1 enum1 254 1 1 Y 256 0 8
+def set1 set1 254 5 3 Y 2048 0 8
+def blob1 blob1 252 255 5 Y 144 0 63
+def blob2 blob2 252 65535 5 Y 144 0 63
+def blob3 blob3 252 16777215 5 Y 144 0 63
+def blob4 blob4 252 4294967295 5 Y 144 0 63
+def dd dd 10 10 10 Y 128 0 63
+def yy yy 13 4 4 Y 32864 0 63
+def tm0 tm0 11 10 8 Y 128 0 63
+def tm3 tm3 11 14 12 Y 128 3 63
+def tm6 tm6 11 17 15 Y 128 6 63
+def dt0 dt0 12 19 19 Y 128 0 63
+def dt3 dt3 12 23 23 Y 128 3 63
+def dt6 dt6 12 26 26 Y 128 6 63
+def ts0 ts0 7 19 19 Y 9376 0 63
+def ts3 ts3 7 23 23 Y 160 3 63
+def ts6 ts6 7 26 26 Y 160 6 63
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+#
+# VIEW
+#
+ALTER TABLE t1 RENAME t0;
+CREATE VIEW t1 AS SELECT * FROM t0;
+CALL p1('create');
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `bit6` bit(6) DEFAULT NULL,
+ `bit7` bit(7) DEFAULT NULL,
+ `bit8` bit(8) DEFAULT NULL,
+ `i1` tinyint(4) DEFAULT NULL,
+ `i2` smallint(6) DEFAULT NULL,
+ `i3` mediumint(9) DEFAULT NULL,
+ `i4` int(11) DEFAULT NULL,
+ `i8` bigint(20) DEFAULT NULL,
+ `ff` float DEFAULT NULL,
+ `fd` double DEFAULT NULL,
+ `dc100` decimal(10,0) DEFAULT NULL,
+ `dc103` decimal(10,3) DEFAULT NULL,
+ `dc209` decimal(20,9) DEFAULT NULL,
+ `cc` varchar(10) DEFAULT NULL,
+ `cv` varchar(10) DEFAULT NULL,
+ `cvu` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `t1` tinytext DEFAULT NULL,
+ `t2` text DEFAULT NULL,
+ `t3` mediumtext DEFAULT NULL,
+ `t4` longtext DEFAULT NULL,
+ `enum1` varchar(1) DEFAULT NULL,
+ `set1` varchar(5) DEFAULT NULL,
+ `blob1` tinyblob DEFAULT NULL,
+ `blob2` blob DEFAULT NULL,
+ `blob3` mediumblob DEFAULT NULL,
+ `blob4` longblob DEFAULT NULL,
+ `dd` date DEFAULT NULL,
+ `yy` year(4) DEFAULT NULL,
+ `tm0` time DEFAULT NULL,
+ `tm3` time(3) DEFAULT NULL,
+ `tm6` time(6) DEFAULT NULL,
+ `dt0` datetime DEFAULT NULL,
+ `dt3` datetime(3) DEFAULT NULL,
+ `dt6` datetime(6) DEFAULT NULL,
+ `ts0` timestamp NULL DEFAULT NULL,
+ `ts3` timestamp(3) NULL DEFAULT NULL,
+ `ts6` timestamp(6) NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+DROP TABLE t2;
+CALL p1('select');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def bit6 bit6 16 6 1 Y 32 0 63
+def bit7 bit7 16 7 1 Y 32 0 63
+def bit8 bit8 16 8 1 Y 32 0 63
+def i1 i1 1 4 2 Y 32768 0 63
+def i2 i2 2 6 2 Y 32768 0 63
+def i3 i3 9 9 2 Y 32768 0 63
+def i4 i4 3 11 2 Y 32768 0 63
+def i8 i8 8 20 2 Y 32768 0 63
+def ff ff 4 12 2 Y 32768 31 63
+def fd fd 5 22 2 Y 32768 31 63
+def dc100 dc100 246 11 2 Y 32768 0 63
+def dc103 dc103 246 12 6 Y 32768 3 63
+def dc209 dc209 246 22 12 Y 32768 9 63
+def cc cc 254 10 4 Y 0 0 8
+def cv cv 253 10 7 Y 0 0 8
+def cvu cvu 253 10 9 Y 0 0 8
+def t1 t1 252 255 5 Y 16 0 8
+def t2 t2 252 65535 5 Y 16 0 8
+def t3 t3 252 16777215 5 Y 16 0 8
+def t4 t4 252 4294967295 5 Y 16 0 8
+def enum1 enum1 254 1 1 Y 256 0 8
+def set1 set1 254 5 3 Y 2048 0 8
+def blob1 blob1 252 255 5 Y 144 0 63
+def blob2 blob2 252 65535 5 Y 144 0 63
+def blob3 blob3 252 16777215 5 Y 144 0 63
+def blob4 blob4 252 4294967295 5 Y 144 0 63
+def dd dd 10 10 10 Y 128 0 63
+def yy yy 13 4 4 Y 32864 0 63
+def tm0 tm0 11 10 8 Y 128 0 63
+def tm3 tm3 11 14 12 Y 128 3 63
+def tm6 tm6 11 17 15 Y 128 6 63
+def dt0 dt0 12 19 19 Y 128 0 63
+def dt3 dt3 12 23 23 Y 128 3 63
+def dt6 dt6 12 26 26 Y 128 6 63
+def ts0 ts0 7 19 19 Y 160 0 63
+def ts3 ts3 7 23 23 Y 160 3 63
+def ts6 ts6 7 26 26 Y 160 6 63
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+DROP VIEW t1;
+DROP TABLE t0;
+DROP PROCEDURE p1;
+#
+# VIEW with subqueries
+#
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,1),(20,2),(30,3),(40,4);
+SELECT AVG(a) FROM t1;
+AVG(a)
+25.0000
+CREATE VIEW v1 AS SELECT a,1 as b FROM t1 WHERE a>(SELECT AVG(a) FROM t1) AND b>(SELECT 1);
+SELECT * FROM v1;
+a b
+30 1
+40 1
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF v1.a DEFAULT 10;
+DECLARE b TYPE OF v1.b DEFAULT 1;
+SELECT a,b;
+END;
+$$
+CALL p1;
+a b
+10 1
+DROP PROCEDURE p1;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+DECLARE a TYPE OF v1.a DEFAULT 10;
+DECLARE b TYPE OF v1.b DEFAULT 1;
+RETURN a+b;
+END;
+$$
+SELECT f1();
+f1()
+11
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# TYPE OF variables + INFORMATION_SCHEMA
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE tables_table_name TYPE OF INFORMATION_SCHEMA.TABLES.TABLE_NAME;
+DECLARE tables_table_rows TYPE OF INFORMATION_SCHEMA.TABLES.TABLE_ROWS;
+DECLARE processlist_info TYPE OF INFORMATION_SCHEMA.PROCESSLIST.INFO;
+DECLARE processlist_info_binary TYPE OF INFORMATION_SCHEMA.PROCESSLIST.INFO_BINARY;
+CREATE TABLE t1 AS SELECT
+tables_table_name,
+tables_table_rows,
+processlist_info,
+processlist_info_binary;
+END;
+$$
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `tables_table_name` varchar(64) CHARACTER SET utf8 DEFAULT NULL,
+ `tables_table_rows` bigint(21) unsigned DEFAULT NULL,
+ `processlist_info` longtext CHARACTER SET utf8 DEFAULT NULL,
+ `processlist_info_binary` blob DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TYPE OF + Table structure change
+# Data type for both a0 and a1 is chosen in the very beginning
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a0 TYPE OF t1.a;
+ALTER TABLE t1 MODIFY a VARCHAR(10); -- This does not affect a1
+BEGIN
+DECLARE a1 TYPE OF t1.a;
+CREATE TABLE t2 AS SELECT a0, a1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END
+$$
+CREATE TABLE t1 (a INT);
+CALL p1;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a0` int(11) DEFAULT NULL,
+ `a1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TYPE OF in parameters
+#
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (b SMALLINT);
+CREATE PROCEDURE p1(a TYPE OF t1.a, b TYPE OF test1.t1.b)
+BEGIN
+CREATE TABLE t2 AS SELECT a, b;
+END;
+$$
+CALL p1('test', 123);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(10) DEFAULT NULL,
+ `b` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+a b
+test 123
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE test1.t1;
+DROP DATABASE test1;
+DROP TABLE t1;
+#
+# TYPE OF in a stored function variables and arguments
+#
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1 (prm TYPE OF t1.a) RETURNS INT
+BEGIN
+DECLARE a TYPE OF t1.a DEFAULT prm;
+RETURN a;
+END;
+$$
+SELECT f1(20);
+f1(20)
+20
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# TYPE OF in function RETURN clause is not supported yet
+#
+CREATE FUNCTION f1() RETURN TYPE OF t1.a
+BEGIN
+RETURN 0;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RETURN TYPE OF t1.a
+BEGIN
+RETURN 0;
+END' at line 1
+#
+# Using TYPE OF variables as FETCH targets
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
+INSERT INTO t1 VALUES (1,'b1','2001-01-01 10:20:30.123');
+INSERT INTO t1 VALUES (2,'b2','2001-01-02 10:20:30.123');
+CREATE TABLE t2 LIKE t1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a TYPE OF t1.a;
+DECLARE v_b TYPE OF t1.b;
+DECLARE v_c TYPE OF t1.c;
+DECLARE c CURSOR FOR SELECT a,b,c FROM t1;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c;
+read_loop: LOOP
+FETCH c INTO v_a, v_b, v_c;
+IF done THEN
+LEAVE read_loop;
+END IF;
+INSERT INTO t2 (a,b,c) VALUES (v_a, v_b, v_c);
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1();
+SELECT * FROM t2;
+a b c
+1 b1 2001-01-01 10:20:30.123
+2 b2 2001-01-02 10:20:30.123
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Using TYPE OF variables as SELECT INTO targets
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
+INSERT INTO t1 VALUES (1,'b1','2001-01-01 10:20:30.123');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE v_a TYPE OF t1.a;
+DECLARE v_b TYPE OF t1.b;
+DECLARE v_c TYPE OF t1.c;
+SELECT * FROM t1 INTO v_a, v_b, v_c;
+SELECT v_a, v_b, v_c;
+END;
+$$
+CALL p1();
+v_a v_b v_c
+1 b1 2001-01-01 10:20:30.123
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result
index ccccacd09a5..3db1e68321c 100644
--- a/mysql-test/r/sp-bugs.result
+++ b/mysql-test/r/sp-bugs.result
@@ -281,3 +281,14 @@ end|
start transaction;
call sp();
drop procedure sp;
+#
+# MDEV-11146 SP variables of the SET data type erroneously allow values with comma
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a SET('a','b','c','a,b');
+SET a='a,b';
+SELECT a, a+0;
+END;
+$$
+ERROR 22007: Illegal set 'a,b' value found during parsing
diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result
index f6a7fff5d4e..972c7ff5b16 100644
--- a/mysql-test/r/sp-code.result
+++ b/mysql-test/r/sp-code.result
@@ -11,7 +11,7 @@ returns int
return 0;
show function code almost_empty;
Pos Instruction
-0 freturn 3 0
+0 freturn int 0
drop function almost_empty;
create procedure code_sample(x int, out err int, out nulls int)
begin
@@ -957,10 +957,10 @@ END
$
SHOW FUNCTION CODE testf_bug11763507;
Pos Instruction
-0 freturn 3 0
+0 freturn int 0
SHOW FUNCTION CODE TESTF_bug11763507;
Pos Instruction
-0 freturn 3 0
+0 freturn int 0
SHOW PROCEDURE CODE testp_bug11763507;
Pos Instruction
0 stmt 0 "SELECT "PROCEDURE testp_bug11763507""
diff --git a/mysql-test/r/sp-cursor.result b/mysql-test/r/sp-cursor.result
new file mode 100644
index 00000000000..d068c19b22b
--- /dev/null
+++ b/mysql-test/r/sp-cursor.result
@@ -0,0 +1,482 @@
+#
+# MDEV-12457 Cursors with parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,'old'),(2,'old'),(3,'old'),(4,'old'),(5,'old');
+CREATE PROCEDURE p1(min INT,max INT)
+BEGIN
+DECLARE done INT DEFAULT FALSE;
+DECLARE va INT;
+DECLARE cur CURSOR(pmin INT, pmax INT) FOR SELECT a FROM t1 WHERE a BETWEEN pmin AND pmax;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN cur(min,max);
+read_loop: LOOP
+FETCH cur INTO va;
+IF done THEN
+LEAVE read_loop;
+END IF;
+INSERT INTO t1 VALUES (va,'new');
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1(2,4);
+SELECT * FROM t1 ORDER BY b DESC,a;
+a b
+1 old
+2 old
+3 old
+4 old
+5 old
+2 new
+3 new
+4 new
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# OPEN with a wrong number of parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a_a INT,a_b VARCHAR(32))
+BEGIN
+DECLARE v_a INT;
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR (p_a INT, p_b VARCHAR(32)) FOR SELECT * FROM t1 WHERE a=p_a;
+OPEN c(a_a);
+CLOSE c;
+END;
+$$
+ERROR 42000: Incorrect parameter count to cursor 'c'
+DROP TABLE t1;
+#
+# Cursor parameters are not visible outside of the cursor
+#
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+DECLARE v_a INT;
+DECLARE c CURSOR (p_a INT) FOR SELECT a FROM t1 WHERE a=p_a;
+OPEN c(a_a);
+SET p_a=10;
+END;
+$$
+ERROR HY000: Unknown system variable 'p_a'
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+DECLARE v_a INT;
+DECLARE c CURSOR (p_a INT) FOR SELECT a FROM t1 WHERE a=p_a;
+SET p_a= 10;
+OPEN c(a_a);
+END;
+$$
+ERROR HY000: Unknown system variable 'p_a'
+#
+# Cursor parameter shadowing a local variable
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE PROCEDURE p1(a INT)
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a INT DEFAULT NULL;
+DECLARE p_a INT DEFAULT NULL;
+DECLARE c CURSOR (p_a VARCHAR(32)) FOR SELECT p_a FROM t1;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c(a);
+read_loop: LOOP
+FETCH c INTO v_a;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT v_a;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1(1);
+v_a
+1
+CALL p1(NULL);
+v_a
+NULL
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Parameters in SELECT list
+#
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR(32))
+BEGIN
+DECLARE v_a INT;
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR (p_a INT, p_b VARCHAR(32)) FOR SELECT p_a,p_b FROM DUAL;
+OPEN c(a_a + 0,a_b);
+FETCH c INTO v_a, v_b;
+SELECT v_a, v_b;
+CLOSE c;
+OPEN c(a_a + 1,a_b);
+FETCH c INTO v_a, v_b;
+SELECT v_a, v_b;
+CLOSE c;
+END;
+$$
+CALL p1(1,'b1');
+v_a v_b
+1 b1
+v_a v_b
+2 b1
+DROP PROCEDURE p1;
+#
+# Parameters in SELECT list + UNION
+#
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR(32))
+BEGIN
+DECLARE v_a INT;
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR(p_a INT, p_b VARCHAR(32)) FOR
+SELECT p_a,p_b FROM DUAL
+UNION ALL
+SELECT p_a+1,CONCAT(p_b,'b') FROM DUAL;
+OPEN c(a_a,a_b);
+FETCH c INTO v_a, v_b;
+SELECT v_a, v_b;
+FETCH c INTO v_a, v_b;
+SELECT v_a, v_b;
+CLOSE c;
+END;
+$$
+CALL p1(1,'b1');
+v_a v_b
+1 b1
+v_a v_b
+2 b1b
+DROP PROCEDURE p1;
+#
+# Parameters in SELECT list + type conversion + warnings
+#
+SET sql_mode='';
+CREATE PROCEDURE p1(a_a VARCHAR(32))
+BEGIN
+DECLARE v_a INT;
+DECLARE c CURSOR (p_a INT) FOR SELECT p_a FROM DUAL;
+OPEN c(a_a);
+FETCH c INTO v_a;
+SELECT v_a;
+CLOSE c;
+END;
+$$
+CALL p1('1b');
+v_a
+1
+Warnings:
+Warning 1265 Data truncated for column 'p_a' at row 1
+CALL p1('b1');
+v_a
+0
+Warnings:
+Warning 1366 Incorrect integer value: 'b1' for column 'p_a' at row 1
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+#
+# One parameter in SELECT list + subselect
+#
+CREATE PROCEDURE p1(a_a VARCHAR(32))
+BEGIN
+DECLARE v_a VARCHAR(10);
+DECLARE c CURSOR (p_a VARCHAR(32)) FOR
+SELECT p_a FROM DUAL UNION SELECT REVERSE(p_a) FROM DUAL;
+OPEN c((SELECT a_a));
+FETCH c INTO v_a;
+SELECT v_a;
+FETCH c INTO v_a;
+SELECT v_a;
+CLOSE c;
+END;
+$$
+CALL p1('ab');
+v_a
+ab
+v_a
+ba
+DROP PROCEDURE p1;
+#
+# Two parameters in SELECT list + subselect
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE v_a VARCHAR(32);
+DECLARE v_b VARCHAR(32);
+DECLARE c CURSOR (p_a VARCHAR(32), p_b VARCHAR(32)) FOR
+SELECT p_a, p_b FROM DUAL
+UNION
+SELECT p_b, p_a FROM DUAL;
+OPEN c((SELECT 'aaa'),(SELECT 'bbb'));
+FETCH c INTO v_a, v_b;
+SELECT v_a, v_b;
+FETCH c INTO v_a, v_b;
+SELECT v_a, v_b;
+CLOSE c;
+END;
+$$
+CALL p1();
+v_a v_b
+aaa bbb
+v_a v_b
+bbb aaa
+DROP PROCEDURE p1;
+#
+# Two parameters in SELECT list + two parameters in WHERE + subselects
+#
+CREATE PROCEDURE p1(a_a VARCHAR(32), a_b VARCHAR(32))
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a VARCHAR(32);
+DECLARE v_b VARCHAR(32);
+DECLARE c CURSOR (value_a VARCHAR(32), value_b VARCHAR(32),
+pattern_a VARCHAR(32), pattern_b VARCHAR(32)) FOR
+SELECT value_a, value_b FROM DUAL WHERE value_a LIKE pattern_a
+UNION
+SELECT value_b, value_a FROM DUAL WHERE value_b LIKE pattern_b;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c((SELECT 'aaa'),(SELECT 'bbb'),(SELECT a_a),(SELECT a_b));
+read_loop: LOOP
+FETCH c INTO v_a, v_b;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT v_a, v_b;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('%','%');
+v_a v_b
+aaa bbb
+v_a v_b
+bbb aaa
+CALL p1('aaa','xxx');
+v_a v_b
+aaa bbb
+CALL p1('xxx','bbb');
+v_a v_b
+bbb aaa
+CALL p1('xxx','xxx');
+DROP PROCEDURE p1;
+#
+# Parameters in SELECT list + stored function
+#
+CREATE FUNCTION f1 (a VARCHAR(32)) RETURNS VARCHAR(32)
+BEGIN
+RETURN CONCAT(a,'y');
+END;
+$$
+CREATE PROCEDURE p1(a_a VARCHAR(32))
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a VARCHAR(10);
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR (p_sel_a VARCHAR(32), p_cmp_a VARCHAR(32)) FOR
+SELECT p_sel_a, p_cmp_a FROM DUAL;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c(f1(a_a), f1(a_a));
+read_loop: LOOP
+FETCH c INTO v_a, v_b;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT v_a, v_b;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('x');
+v_a v_b
+xy xy
+CALL p1(f1(COALESCE(NULL, f1('x'))));
+v_a v_b
+xyyy xyyy
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+#
+# One parameter in WHERE clause
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a INT;
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR (p_a INT) FOR SELECT a,b FROM t1 WHERE a=p_a;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c(a_a);
+read_loop: LOOP
+FETCH c INTO v_a, v_b;
+IF done THEN
+LEAVE read_loop;
+END IF;
+INSERT INTO t2 VALUES (v_a,v_b);
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1(1);
+SELECT * FROM t2;
+a b
+1 11
+1 12
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+#
+# Two parameters in WHERE clause
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR(32))
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a INT;
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR (p_a INT, p_b VARCHAR(32)) FOR SELECT a,b FROM t1 WHERE a=p_a AND b=p_b;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c(a_a, a_b);
+read_loop: LOOP
+FETCH c INTO v_a, v_b;
+IF done THEN
+LEAVE read_loop;
+END IF;
+INSERT INTO t2 VALUES (v_a,v_b);
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1(1,'11');
+SELECT * FROM t2;
+a b
+1 11
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+#
+# Parameters in WHERE and HAVING clauses
+#
+CREATE TABLE t1 (name VARCHAR(10), value INT);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bot',1);
+CREATE PROCEDURE p1 (arg_name_limit VARCHAR(32), arg_total_limit INT)
+BEGIN
+DECLARE i INT DEFAULT 0;
+DECLARE v_name VARCHAR(10);
+DECLARE v_total INT;
+-- +0 is needed to work around the bug MDEV-11081
+DECLARE c CURSOR(p_v INT) FOR
+SELECT name, SUM(value + p_v) + 0 AS total FROM t1
+WHERE name LIKE arg_name_limit
+GROUP BY name HAVING total>=arg_total_limit;
+WHILE i < 2 DO
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+OPEN c(i);
+read_loop: LOOP
+FETCH c INTO v_name, v_total;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT v_name, v_total;
+END LOOP;
+CLOSE c;
+SET i= i + 1;
+END;
+END WHILE;
+END;
+$$
+CALL p1('%', 2);
+v_name v_total
+bin 2
+v_name v_total
+but 3
+v_name v_total
+bin 4
+v_name v_total
+bot 2
+v_name v_total
+but 6
+CALL p1('b_t', 0);
+v_name v_total
+bot 1
+v_name v_total
+but 3
+v_name v_total
+bot 2
+v_name v_total
+but 6
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# One parameter in LIMIT clause
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'b1');
+INSERT INTO t1 VALUES (2,'b2');
+INSERT INTO t1 VALUES (3,'b3');
+INSERT INTO t1 VALUES (4,'b4');
+INSERT INTO t1 VALUES (5,'b5');
+INSERT INTO t1 VALUES (6,'b6');
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+DECLARE done INT DEFAULT 0;
+DECLARE v_a INT;
+DECLARE v_b VARCHAR(10);
+DECLARE c CURSOR (p_a INT) FOR SELECT a,b FROM t1 ORDER BY a LIMIT p_a;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+OPEN c(a_a);
+read_loop: LOOP
+FETCH c INTO v_a, v_b;
+IF done THEN
+LEAVE read_loop;
+END IF;
+INSERT INTO t2 VALUES (v_a,v_b);
+END LOOP;
+CLOSE c;
+SELECT * FROM t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1(1);
+a b
+1 b1
+CALL p1(3);
+a b
+1 b1
+2 b2
+3 b3
+CALL p1(6);
+a b
+1 b1
+2 b2
+3 b3
+4 b4
+5 b5
+6 b6
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-12457 Cursors with parameters
+#
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 6fbe2d62fd7..f8dd2737e8e 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -1504,7 +1504,7 @@ ERROR 42000: FUNCTION inexistent does not exist
SELECT .inexistent();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '()' at line 1
SELECT ..inexistent();
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.inexistent()' at line 1
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '..inexistent()' at line 1
USE test;
create function f1() returns int
begin
@@ -1990,6 +1990,8 @@ Warning 1264 Out of range value for column 'a' at row 1
Note 1292 Truncated incorrect INTEGER value: '222222 '
Warning 1264 Out of range value for column 'b' at row 1
Error 1048 Column 'c' cannot be null
+Note 4070 At line 6 in test.t1_bi
+Note 4070 At line 2 in test.p1
DROP TABLE t1;
DROP TABLE t2;
diff --git a/mysql-test/r/sp-group.result b/mysql-test/r/sp-group.result
index 2e30b697103..0fc8d45c5b1 100644
--- a/mysql-test/r/sp-group.result
+++ b/mysql-test/r/sp-group.result
@@ -3,7 +3,7 @@ Warnings:
Note 1051 Unknown table 'test.t1'
drop view if exists view_t1;
Warnings:
-Note 1051 Unknown table 'test.view_t1'
+Note 4068 Unknown VIEW: 'test.view_t1'
SET sql_mode=ONLY_FULL_GROUP_BY;
CREATE TABLE t1 (
pk INT,
diff --git a/mysql-test/r/sp-row.result b/mysql-test/r/sp-row.result
new file mode 100644
index 00000000000..c3204fe043b
--- /dev/null
+++ b/mysql-test/r/sp-row.result
@@ -0,0 +1,2248 @@
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+#
+# ROW of ROWs is not supported yet
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a ROW(a INT));
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT));
+END' at line 3
+#
+# Returning the entire ROW parameter from a function
+#
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURNS INT
+BEGIN
+RETURN a;
+END;
+$$
+SELECT f1(ROW(10,20));
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# ROW as an SP parameter
+#
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURNS INT
+BEGIN
+RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+SELECT f1(a);
+END;
+$$
+SELECT f1(ROW(10,20));
+f1(ROW(10,20))
+20
+SELECT f1(10);
+ERROR 21000: Operand should contain 2 column(s)
+SELECT f1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1();
+f1(a)
+21
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CALL p1(ROW(10,20));
+a.a a.b
+10 20
+CALL p1(10);
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# ROW as an SP OUT parameter
+#
+CREATE PROCEDURE p1(OUT a ROW(a INT,b INT))
+BEGIN
+SET a.a=10;
+SET a.b=20;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+CALL p1(a);
+SELECT a.a,a.b;
+END;
+$$
+CALL p2();
+a.a a.b
+10 20
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+#
+# ROW as an SP return value is not supported yet
+#
+CREATE FUNCTION p1() RETURNS ROW(a INT)
+BEGIN
+RETURN NULL;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT)
+BEGIN
+RETURN NULL;
+END' at line 1
+#
+# Diplicate row field
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT, a DOUBLE);
+SELECT a.a;
+END;
+$$
+ERROR 42S21: Duplicate column name 'a'
+#
+# Bad scalar default value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT, b DOUBLE) DEFAULT 1;
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Bad ROW default value with a wrong number of fields
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT, b DOUBLE) DEFAULT ROW(1,2,3);
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Scalar variable vs table alias cause no ambiguity
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT;
+-- a.x is a table column here (not a row variable field)
+SELECT a.x FROM a;
+SELECT a.x FROM t1 a;
+END;
+$$
+DROP PROCEDURE p1;
+#
+# Using the entire ROW variable in select list
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT);
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW variable in functions
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT);
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT);
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Comparing the entire ROW to a scalar value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT a=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT 1=a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Passing the entire ROW to a stored function
+#
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+RETURN a;
+END;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT f1(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+#
+# Assigning a scalar value to a ROW variable with 1 column
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a scalar value to a ROW variable with 2 columns
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a ROW value to a ROW variable with different number of columns
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec=ROW(1,2,3);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Returning the entire ROW from a function is not supported yet
+# This syntax would be needed: SELECT f1().x FROM DUAL;
+#
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+DECLARE rec ROW(a INT);
+RETURN rec;
+END;
+$$
+SELECT f1(10);
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# Using the entire ROW in SELECT..CREATE
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW in LIMIT
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= '10';
+SELECT * FROM t1 LIMIT rec;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# Setting ROW fields using a SET command
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+DECLARE a INT;
+SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c a
+10 20 test 5
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from a ROW value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec=ROW(1,2);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1();
+rec.a rec.b
+1 2
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from another ROW value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT,b INT);
+DECLARE rec2 ROW(a INT,b INT);
+SET rec1=ROW(1,2);
+SET rec2=rec1;
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+1 2
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to a ROW() function
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec.a= 1;
+SET rec.b= 2;
+SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+SELECT rec=(NULL,0), rec=ROW(NULL,0);
+SELECT rec=(NULL,2), rec=ROW(NULL,2);
+SELECT rec<>(0,0), rec<>ROW(0,0);
+SELECT rec<>(1,2), rec<>ROW(1,2);
+SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+SELECT rec IN ((0,NULL),(1,2));
+SELECT rec NOT IN ((0,NULL),(1,1));
+SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+CALL p1();
+rec=(0,0) rec=ROW(0,0) (0,0)=rec ROW(0,0)=rec
+0 0 0 0
+rec=(1,2) rec=ROW(1,2) (1,2)=rec ROW(1,2)=rec
+1 1 1 1
+rec=(NULL,0) rec=ROW(NULL,0)
+0 0
+rec=(NULL,2) rec=ROW(NULL,2)
+NULL NULL
+rec<>(0,0) rec<>ROW(0,0)
+1 1
+rec<>(1,2) rec<>ROW(1,2)
+0 0
+rec<>(NULL,0) rec<>ROW(NULL,0)
+1 1
+rec<>(NULL,2) rec<>ROW(NULL,2)
+NULL NULL
+rec IN ((0,0)) rec IN (ROW(0,0))
+0 0
+rec IN ((1,2)) rec IN (ROW(1,2))
+1 1
+rec IN ((0,NULL),(1,2))
+1
+rec NOT IN ((0,NULL),(1,1))
+1
+rec NOT IN ((1,NULL),(1,1))
+NULL
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to another ROW variable
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec1,rec2,rec3 ROW(a INT,b INT);
+SET rec1.a= 1;
+SET rec1.b= 2;
+SET rec2.a= 11;
+SET rec2.b= 12;
+SET rec3.a= 11;
+SET rec3.b= 12;
+SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+CALL p1();
+rec1=rec2 rec2=rec1 rec2=rec3 rec3=rec2
+0 0 1 1
+DROP PROCEDURE p1;
+#
+# Referencing a non-existing row variable
+#
+CREATE PROCEDURE p1()
+BEGIN
+SET a.b=1;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'a'
+#
+# Referencing a non-existing row field
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT,b INT);
+SELECT a.c FROM t1;
+END;
+$$
+ERROR HY000: Row variable 'a' does not have a field 'c'
+#
+# ROW and scalar variables with the same name shadowing each other
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT);
+SET a.a=100;
+SELECT a.a;
+BEGIN
+DECLARE a INT DEFAULT 200;
+SELECT a;
+BEGIN
+DECLARE a ROW(a INT);
+SET a.a=300;
+SELECT a.a;
+END;
+SELECT a;
+END;
+SELECT a.a;
+END;
+$$
+CALL p1();
+a.a
+100
+a
+200
+a.a
+300
+a
+200
+a.a
+100
+DROP PROCEDURE p1;
+#
+# ROW with good default values
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT,b INT) DEFAULT (10,20);
+DECLARE b ROW(a INT,b INT) DEFAULT (11,21);
+DECLARE c ROW(a INT,b INT) DEFAULT a;
+SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+CALL p1;
+a.a a.b b.a b.b c.a c.b
+10 20 11 21 10 20
+DROP PROCEDURE p1;
+#
+# ROW in WHERE clause
+#
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT) DEFAULT ROW(10,20);
+SELECT * FROM t1 WHERE rec=ROW(a,b);
+SELECT * FROM t1 WHERE ROW(a,b)=rec;
+SELECT * FROM t1 WHERE rec=ROW(10,20);
+SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+CALL p1();
+a b
+10 20
+a b
+10 20
+a b
+10 20
+a b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in WHERE clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= 10;
+SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in HAVING clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= 10;
+SELECT * FROM t1 HAVING a=rec.a;
+SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in LIMIT clause
+#
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 LIMIT t1.a;
+ERROR 42000: Undeclared variable: t1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= 10;
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+a
+10
+20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a VARCHAR(10));
+SET rec.a= '10';
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# ROW fields in select list
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE t1 ROW(a INT);
+SET t1.a= 10;
+SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+CALL p1();
+t1.a comm
+10 This is the variable t1.a value, rather than the column t1.a
+10 This is the variable t1.a value, rather than the column t1.a
+t1.a a t1.a+t2.a
+10 10 20
+10 20 30
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as insert values
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10));
+SET rec.a= 10;
+SET rec.b= 'test';
+INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 test
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as SP out parameters
+#
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+SET a= 10;
+SET b= 'test';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10));
+CALL p1(rec.a, rec.b);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as dynamic SQL out parameters
+#
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+SET a= 20;
+SET b= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(30));
+EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+20 test-dynamic-sql
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as SELECT..INTO targets
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10));
+SELECT 10,'test' INTO rec.a,rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+#
+# Implicit default NULL handling
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d rec.e rec.f
+NULL NULL NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# NULL handling
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT (NULL,NULL);
+DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (10,20);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (NULL,20);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (10,NULL);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (NULL,NULL);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+CALL p1;
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+rec1.a rec1.b rec2.a rec2.b
+10 20 10 20
+rec1.a rec1.b rec2.a rec2.b
+NULL 20 NULL 20
+rec1.a rec1.b rec2.a rec2.b
+10 NULL 10 NULL
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# Testing multiple ROW variable declarations
+# This makes sure that fill_field_definitions() is called only once
+# per a ROW field, so create length is not converted to internal length
+# multiple times.
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `rec1.a` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec2.a` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec3.a` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# INT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var INT; DECLARE rec ROW(var INT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(1); DECLARE rec ROW(var INT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(2); DECLARE rec ROW(var INT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(3); DECLARE rec ROW(var INT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(4); DECLARE rec ROW(var INT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(5); DECLARE rec ROW(var INT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(6); DECLARE rec ROW(var INT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(7); DECLARE rec ROW(var INT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(8); DECLARE rec ROW(var INT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(9); DECLARE rec ROW(var INT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(10); DECLARE rec ROW(var INT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(11); DECLARE rec ROW(var INT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(11) DEFAULT NULL,
+ `rec.var` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(12); DECLARE rec ROW(var INT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(12) DEFAULT NULL,
+ `rec.var` int(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(13); DECLARE rec ROW(var INT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(13) DEFAULT NULL,
+ `rec.var` int(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(14); DECLARE rec ROW(var INT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(14) DEFAULT NULL,
+ `rec.var` int(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(20); DECLARE rec ROW(var INT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(20) DEFAULT NULL,
+ `rec.var` int(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(21); DECLARE rec ROW(var INT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(21) DEFAULT NULL,
+ `rec.var` int(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TINYINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT; DECLARE rec ROW(var TINYINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(4) DEFAULT NULL,
+ `rec.var` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(1); DECLARE rec ROW(var TINYINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(4) DEFAULT NULL,
+ `rec.var` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(2); DECLARE rec ROW(var TINYINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(4) DEFAULT NULL,
+ `rec.var` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(3); DECLARE rec ROW(var TINYINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(4) DEFAULT NULL,
+ `rec.var` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(4); DECLARE rec ROW(var TINYINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(4) DEFAULT NULL,
+ `rec.var` tinyint(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(5); DECLARE rec ROW(var TINYINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(5) DEFAULT NULL,
+ `rec.var` tinyint(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(6); DECLARE rec ROW(var TINYINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(6) DEFAULT NULL,
+ `rec.var` tinyint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(7); DECLARE rec ROW(var TINYINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(7) DEFAULT NULL,
+ `rec.var` tinyint(7) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(8); DECLARE rec ROW(var TINYINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(8) DEFAULT NULL,
+ `rec.var` tinyint(8) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(9); DECLARE rec ROW(var TINYINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(9) DEFAULT NULL,
+ `rec.var` tinyint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(10); DECLARE rec ROW(var TINYINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(10) DEFAULT NULL,
+ `rec.var` tinyint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(11); DECLARE rec ROW(var TINYINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(11) DEFAULT NULL,
+ `rec.var` tinyint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(12); DECLARE rec ROW(var TINYINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(12) DEFAULT NULL,
+ `rec.var` tinyint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(13); DECLARE rec ROW(var TINYINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(13) DEFAULT NULL,
+ `rec.var` tinyint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(14); DECLARE rec ROW(var TINYINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(14) DEFAULT NULL,
+ `rec.var` tinyint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(20); DECLARE rec ROW(var TINYINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(20) DEFAULT NULL,
+ `rec.var` tinyint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(21); DECLARE rec ROW(var TINYINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinyint(21) DEFAULT NULL,
+ `rec.var` tinyint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SMALLINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT; DECLARE rec ROW(var SMALLINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(1); DECLARE rec ROW(var SMALLINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(2); DECLARE rec ROW(var SMALLINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(3); DECLARE rec ROW(var SMALLINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(4); DECLARE rec ROW(var SMALLINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(5); DECLARE rec ROW(var SMALLINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(6); DECLARE rec ROW(var SMALLINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(6) DEFAULT NULL,
+ `rec.var` smallint(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(7); DECLARE rec ROW(var SMALLINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(7) DEFAULT NULL,
+ `rec.var` smallint(7) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(8); DECLARE rec ROW(var SMALLINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(8) DEFAULT NULL,
+ `rec.var` smallint(8) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(9); DECLARE rec ROW(var SMALLINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(9) DEFAULT NULL,
+ `rec.var` smallint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(10); DECLARE rec ROW(var SMALLINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(10) DEFAULT NULL,
+ `rec.var` smallint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(11); DECLARE rec ROW(var SMALLINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(11) DEFAULT NULL,
+ `rec.var` smallint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(12); DECLARE rec ROW(var SMALLINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(12) DEFAULT NULL,
+ `rec.var` smallint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(13); DECLARE rec ROW(var SMALLINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(13) DEFAULT NULL,
+ `rec.var` smallint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(14); DECLARE rec ROW(var SMALLINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(14) DEFAULT NULL,
+ `rec.var` smallint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(20); DECLARE rec ROW(var SMALLINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(20) DEFAULT NULL,
+ `rec.var` smallint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(21); DECLARE rec ROW(var SMALLINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` smallint(21) DEFAULT NULL,
+ `rec.var` smallint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MEDIUMINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT; DECLARE rec ROW(var MEDIUMINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(1); DECLARE rec ROW(var MEDIUMINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(2); DECLARE rec ROW(var MEDIUMINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(3); DECLARE rec ROW(var MEDIUMINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(4); DECLARE rec ROW(var MEDIUMINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(5); DECLARE rec ROW(var MEDIUMINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(6); DECLARE rec ROW(var MEDIUMINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(7); DECLARE rec ROW(var MEDIUMINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(8); DECLARE rec ROW(var MEDIUMINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(9); DECLARE rec ROW(var MEDIUMINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(9) DEFAULT NULL,
+ `rec.var` mediumint(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(10); DECLARE rec ROW(var MEDIUMINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(10) DEFAULT NULL,
+ `rec.var` mediumint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(11); DECLARE rec ROW(var MEDIUMINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(11) DEFAULT NULL,
+ `rec.var` mediumint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(12); DECLARE rec ROW(var MEDIUMINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(12) DEFAULT NULL,
+ `rec.var` mediumint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(13); DECLARE rec ROW(var MEDIUMINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(13) DEFAULT NULL,
+ `rec.var` mediumint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(14); DECLARE rec ROW(var MEDIUMINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(14) DEFAULT NULL,
+ `rec.var` mediumint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(20); DECLARE rec ROW(var MEDIUMINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(20) DEFAULT NULL,
+ `rec.var` mediumint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(21); DECLARE rec ROW(var MEDIUMINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumint(21) DEFAULT NULL,
+ `rec.var` mediumint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# BIGINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT; DECLARE rec ROW(var BIGINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(1); DECLARE rec ROW(var BIGINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(2); DECLARE rec ROW(var BIGINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(3); DECLARE rec ROW(var BIGINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(4); DECLARE rec ROW(var BIGINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(5); DECLARE rec ROW(var BIGINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(6); DECLARE rec ROW(var BIGINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(7); DECLARE rec ROW(var BIGINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(8); DECLARE rec ROW(var BIGINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(9); DECLARE rec ROW(var BIGINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(10); DECLARE rec ROW(var BIGINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(11); DECLARE rec ROW(var BIGINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(12); DECLARE rec ROW(var BIGINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(13); DECLARE rec ROW(var BIGINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(14); DECLARE rec ROW(var BIGINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(20); DECLARE rec ROW(var BIGINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(21); DECLARE rec ROW(var BIGINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(21) DEFAULT NULL,
+ `rec.var` bigint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DOUBLE
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE; DECLARE rec ROW(var DOUBLE); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double DEFAULT NULL,
+ `rec.var` double DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,1); DECLARE rec ROW(var DOUBLE(30,1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,1) DEFAULT NULL,
+ `rec.var` double(30,1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,2); DECLARE rec ROW(var DOUBLE(30,2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,2) DEFAULT NULL,
+ `rec.var` double(30,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,3); DECLARE rec ROW(var DOUBLE(30,3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,3) DEFAULT NULL,
+ `rec.var` double(30,3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,4); DECLARE rec ROW(var DOUBLE(30,4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,4) DEFAULT NULL,
+ `rec.var` double(30,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,5); DECLARE rec ROW(var DOUBLE(30,5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,5) DEFAULT NULL,
+ `rec.var` double(30,5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,6); DECLARE rec ROW(var DOUBLE(30,6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,6) DEFAULT NULL,
+ `rec.var` double(30,6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,7); DECLARE rec ROW(var DOUBLE(30,7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,7) DEFAULT NULL,
+ `rec.var` double(30,7) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,8); DECLARE rec ROW(var DOUBLE(30,8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,8) DEFAULT NULL,
+ `rec.var` double(30,8) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,9); DECLARE rec ROW(var DOUBLE(30,9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,9) DEFAULT NULL,
+ `rec.var` double(30,9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,10); DECLARE rec ROW(var DOUBLE(30,10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,10) DEFAULT NULL,
+ `rec.var` double(30,10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,11); DECLARE rec ROW(var DOUBLE(30,11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,11) DEFAULT NULL,
+ `rec.var` double(30,11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,12); DECLARE rec ROW(var DOUBLE(30,12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,12) DEFAULT NULL,
+ `rec.var` double(30,12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,13); DECLARE rec ROW(var DOUBLE(30,13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,13) DEFAULT NULL,
+ `rec.var` double(30,13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,14); DECLARE rec ROW(var DOUBLE(30,14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,14) DEFAULT NULL,
+ `rec.var` double(30,14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,20); DECLARE rec ROW(var DOUBLE(30,20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,20) DEFAULT NULL,
+ `rec.var` double(30,20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,21); DECLARE rec ROW(var DOUBLE(30,21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,21) DEFAULT NULL,
+ `rec.var` double(30,21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# VARCHAR
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var CHAR; DECLARE rec ROW(var CHAR); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(1) DEFAULT NULL,
+ `rec.var` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BINARY; DECLARE rec ROW(var BINARY); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varbinary(1) DEFAULT NULL,
+ `rec.var` varbinary(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var CHAR(1); DECLARE rec ROW(var CHAR(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(1) DEFAULT NULL,
+ `rec.var` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var CHAR(10); DECLARE rec ROW(var CHAR(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) DEFAULT NULL,
+ `rec.var` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var NCHAR(10); DECLARE rec ROW(var NCHAR(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BINARY(10); DECLARE rec ROW(var BINARY(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varbinary(10) DEFAULT NULL,
+ `rec.var` varbinary(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARBINARY(10); DECLARE rec ROW(var VARBINARY(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varbinary(10) DEFAULT NULL,
+ `rec.var` varbinary(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARCHAR(10); DECLARE rec ROW(var VARCHAR(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) DEFAULT NULL,
+ `rec.var` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARCHAR(10) CHARACTER SET utf8; DECLARE rec ROW(var VARCHAR(10) CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin; DECLARE rec ROW(var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
+ `rec.var` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TIME
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME; DECLARE rec ROW(var TIME); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time DEFAULT NULL,
+ `rec.var` time DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(1); DECLARE rec ROW(var TIME(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(1) DEFAULT NULL,
+ `rec.var` time(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(2); DECLARE rec ROW(var TIME(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(2) DEFAULT NULL,
+ `rec.var` time(2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(3); DECLARE rec ROW(var TIME(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(3) DEFAULT NULL,
+ `rec.var` time(3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(4); DECLARE rec ROW(var TIME(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(4) DEFAULT NULL,
+ `rec.var` time(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(5); DECLARE rec ROW(var TIME(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(5) DEFAULT NULL,
+ `rec.var` time(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(6); DECLARE rec ROW(var TIME(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(6) DEFAULT NULL,
+ `rec.var` time(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DATETIME
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME; DECLARE rec ROW(var DATETIME); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime DEFAULT NULL,
+ `rec.var` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(1); DECLARE rec ROW(var DATETIME(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(1) DEFAULT NULL,
+ `rec.var` datetime(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(2); DECLARE rec ROW(var DATETIME(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(2) DEFAULT NULL,
+ `rec.var` datetime(2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(3); DECLARE rec ROW(var DATETIME(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(3) DEFAULT NULL,
+ `rec.var` datetime(3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(4); DECLARE rec ROW(var DATETIME(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(4) DEFAULT NULL,
+ `rec.var` datetime(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(5); DECLARE rec ROW(var DATETIME(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(5) DEFAULT NULL,
+ `rec.var` datetime(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(6); DECLARE rec ROW(var DATETIME(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(6) DEFAULT NULL,
+ `rec.var` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# LOB
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var TEXT; DECLARE rec ROW(var TEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` text DEFAULT NULL,
+ `rec.var` text DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYTEXT; DECLARE rec ROW(var TINYTEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` tinytext DEFAULT NULL,
+ `rec.var` tinytext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMTEXT; DECLARE rec ROW(var MEDIUMTEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumtext DEFAULT NULL,
+ `rec.var` mediumtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var LONGTEXT; DECLARE rec ROW(var LONGTEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` longtext DEFAULT NULL,
+ `rec.var` longtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TEXT CHARACTER SET utf8; DECLARE rec ROW(var TEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumtext CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` mediumtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYTEXT CHARACTER SET utf8; DECLARE rec ROW(var TINYTEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` text CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` text CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMTEXT CHARACTER SET utf8; DECLARE rec ROW(var MEDIUMTEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` longtext CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` longtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var LONGTEXT CHARACTER SET utf8; DECLARE rec ROW(var LONGTEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` longtext CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` longtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
+#
+# MDEV-12291 Allow ROW variables as SELECT INTO targets
+#
+# ROW variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(32), c DOUBLE);
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: The used SELECT statements have a different number of columns
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# Multiple ROW variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(32));
+SELECT * FROM t1 INTO rec1, rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# ROW variables working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(32));
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MDEV-13273 Confusion between table alias and ROW type variable
+#
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT;
+DECLARE b INT;
+-- a.c1 is a table column
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 0;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (c1 INT, c2 INT) DEFAULT ROW(101,102);
+DECLARE b INT;
+-- a.c1 is a ROW variable field
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 102;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+101
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW TYPE OF t1 DEFAULT ROW (10,20);
+DECLARE b INT;
+-- a.c1 is a ROW variable field
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 20;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+10
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+BEGIN
+DECLARE a ROW TYPE OF cur1 DEFAULT ROW (10,20);
+DECLARE b INT;
+-- a.c1 is a ROW variable field
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 20;
+SELECT b;
+END;
+END;
+$$
+CALL p1;
+b
+10
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/r/sp-security-anchor-type.result b/mysql-test/r/sp-security-anchor-type.result
new file mode 100644
index 00000000000..4ee846f9f2e
--- /dev/null
+++ b/mysql-test/r/sp-security-anchor-type.result
@@ -0,0 +1,263 @@
+#
+# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+#
+# Initiation:
+# - creating database db1
+# - creating user user1 with access rights to db1
+#
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (a INT, b VARCHAR(10));
+CREATE USER user1;
+GRANT ALL PRIVILEGES ON test.* TO user1;
+connect conn1,localhost,user1,,test;
+SELECT database();
+database()
+test
+SELECT user();
+user()
+user1@localhost
+#
+# Making sure that user1 does not have privileges to db1.t1
+#
+SHOW CREATE TABLE db1.t1;
+ERROR 42000: SHOW command denied to user 'user1'@'localhost' for table 't1'
+SHOW FIELDS IN db1.t1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+#
+# Trigger: using TYPE OF with a table we don't have access to
+#
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+a b
+10 20
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+DECLARE b TYPE OF db1.t1.b DEFAULT 20;
+SET NEW.b = 10;
+END
+$$
+INSERT INTO t1 (a) VALUES (10);
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+SELECT * FROM t1;
+a b
+10 20
+DROP TRIGGER tr1;
+DROP TABLE t1;
+#
+# Stored procedure: Using TYPE OF for with a table that we don't have access to
+# DEFINER user1, SQL SECURITY DEFAULT
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+SELECT a;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+#
+# Stored procedure: Using TYPE OF for with a table that we don't have access to
+# DEFINER root, SQL SECURITY INVOKER
+#
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+SELECT a;
+END;
+$$
+connection conn1;
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+BEGIN
+DECLARE a ROW TYPE OF db1.t1;
+SELECT a.a;
+END;
+$$
+connection conn1;
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+#
+# Stored procedure: Using TYPE OF for with a table that we don't have access to
+# DEFINER root, SQL SECURITY DEFINER
+#
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+SELECT a;
+END;
+$$
+connection conn1;
+CALL p1;
+a
+10
+DROP PROCEDURE p1;
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+BEGIN
+DECLARE a ROW TYPE OF db1.t1;
+SET a.a= 10;
+SELECT a.a;
+END;
+$$
+connection conn1;
+CALL p1;
+a.a
+10
+DROP PROCEDURE p1;
+#
+# Stored function: Using TYPE OF for with a table that we don't have access to
+# DEFINER user1, SQL SECURITY DEFAULT
+#
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 0;
+RETURN OCTET_LENGTH(a);
+END;
+$$
+SELECT f1();
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Stored function: Using TYPE OF for with a table that we don't have access to
+# DEFINER root, SQL SECURITY INVOKER
+#
+connection default;
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1() RETURNS INT
+SQL SECURITY INVOKER
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 0;
+RETURN OCTET_LENGTH(a);
+END;
+$$
+connection conn1;
+SELECT f1();
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Stored function: Using TYPE OF for with a table that we don't have access to
+# DEFINER root, SQL SECURITY DEFINER
+#
+connection default;
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1() RETURNS INT
+SQL SECURITY DEFINER
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 0;
+RETURN OCTET_LENGTH(a);
+END;
+$$
+connection conn1;
+SELECT f1();
+f1()
+1
+DROP FUNCTION f1;
+DROP TABLE t1;
+connection default;
+GRANT SELECT (a) ON db1.t1 TO user1;
+connection conn1;
+#
+# Making sure that user1 has access to db1.t1.a, but not to db1.t1.b
+#
+SHOW CREATE TABLE db1.t1;
+ERROR 42000: SHOW command denied to user 'user1'@'localhost' for table 't1'
+SHOW FIELDS IN db1.t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+#
+# Trigger: Per-column privileges
+#
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+a b
+10 20
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 20;
+BEGIN
+SET NEW.b := 10;
+END;
+END
+$$
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+a b
+10 20
+10 10
+DROP TRIGGER tr1;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+DECLARE b TYPE OF db1.t1.b DEFAULT 20;
+BEGIN
+SET NEW.b = 10;
+END;
+END
+$$
+INSERT INTO t1 (a) VALUES (10);
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
+SELECT * FROM t1;
+a b
+10 20
+10 10
+DROP TRIGGER tr1;
+DROP TABLE t1;
+#
+# Stored procedure: Per-column privileges
+# DEFINER user1, SQL SECURITY DEFAULT
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+SELECT a;
+END;
+$$
+CALL p1;
+a
+10
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE b TYPE OF db1.t1.b DEFAULT 10;
+SELECT b;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE b ROW TYPE OF db1.t1;
+SET b.b=10;
+SELECT b.b;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
+DROP PROCEDURE p1;
+#
+# Clean up
+#
+disconnect conn1;
+connection default;
+DROP USER user1;
+DROP DATABASE db1;
+#
+# End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result
index 0a7ea0d68c5..ac1566d0c6e 100644
--- a/mysql-test/r/sp-vars.result
+++ b/mysql-test/r/sp-vars.result
@@ -673,7 +673,6 @@ vb IS TRUE;
END|
call p1();
HEX(b) b = 0 b = FALSE b IS FALSE b = 1 b = TRUE b IS TRUE
-
0 1 1 1 0 0 0
1 0 0 0 1 1 1
call p2();
@@ -1185,3 +1184,60 @@ CALL vctest();
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'string'
DROP PROCEDURE vctest;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12876 Wrong data type for CREATE..SELECT sp_var
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE i8 TINYINT;
+DECLARE i16 SMALLINT;
+DECLARE i32 INT;
+DECLARE i64 BIGINT;
+DECLARE f FLOAT;
+DECLARE d DOUBLE;
+DECLARE b8 BIT(8);
+DECLARE y YEAR;
+DECLARE t1 TINYTEXT;
+DECLARE t2 TEXT;
+DECLARE t3 MEDIUMTEXT;
+DECLARE t4 LONGTEXT;
+CREATE TABLE t1 AS SELECT i8, i16, i32, i64, f, d, b8, y, t1, t2, t3, t4;
+END;
+$$
+CALL p1;
+DESCRIBE t1;
+Field Type Null Key Default Extra
+i8 tinyint(4) YES NULL
+i16 smallint(6) YES NULL
+i32 int(11) YES NULL
+i64 bigint(20) YES NULL
+f float YES NULL
+d double YES NULL
+b8 bit(8) YES NULL
+y year(4) YES NULL
+t1 tinytext YES NULL
+t2 text YES NULL
+t3 mediumtext YES NULL
+t4 longtext YES NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MDEV-12917 Wrong data type for CREATE..SELECT year_sp_variable
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a YEAR;
+CREATE OR REPLACE TABLE t1 AS SELECT a;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+END;
+$$
+CALL p1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" year(4) DEFAULT NULL
+)
+DROP PROCEDURE p1;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 47adafa93ba..71ca5de2990 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3211,7 +3211,7 @@ drop procedure bug10961|
DROP PROCEDURE IF EXISTS bug6866|
DROP VIEW IF EXISTS tv|
Warnings:
-Note 1051 Unknown table 'test.tv'
+Note 4068 Unknown VIEW: 'test.tv'
DROP TABLE IF EXISTS tt1,tt2,tt3|
Warnings:
Note 1051 Unknown table 'test.tt1'
@@ -4329,57 +4329,57 @@ Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair status OK
-test.v1 repair Error 'test.v1' is not BASE TABLE
+test.v1 repair Error 'test.v1' is not of type 'BASE TABLE'
test.v1 repair status Operation failed
Table Op Msg_type Msg_text
test.t1 optimize status OK
test.t2 optimize status OK
test.t3 optimize status OK
-test.v1 optimize Error 'test.v1' is not BASE TABLE
+test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE'
test.v1 optimize status Operation failed
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
test.t2 analyze status Table is already up to date
test.t3 analyze status Table is already up to date
-test.v1 analyze Error 'test.v1' is not BASE TABLE
+test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE'
test.v1 analyze status Operation failed
call bug13012()|
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair status OK
-test.v1 repair Error 'test.v1' is not BASE TABLE
+test.v1 repair Error 'test.v1' is not of type 'BASE TABLE'
test.v1 repair status Operation failed
Table Op Msg_type Msg_text
test.t1 optimize status OK
test.t2 optimize status OK
test.t3 optimize status OK
-test.v1 optimize Error 'test.v1' is not BASE TABLE
+test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE'
test.v1 optimize status Operation failed
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
test.t2 analyze status Table is already up to date
test.t3 analyze status Table is already up to date
-test.v1 analyze Error 'test.v1' is not BASE TABLE
+test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE'
test.v1 analyze status Operation failed
call bug13012()|
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair status OK
-test.v1 repair Error 'test.v1' is not BASE TABLE
+test.v1 repair Error 'test.v1' is not of type 'BASE TABLE'
test.v1 repair status Operation failed
Table Op Msg_type Msg_text
test.t1 optimize status OK
test.t2 optimize status OK
test.t3 optimize status OK
-test.v1 optimize Error 'test.v1' is not BASE TABLE
+test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE'
test.v1 optimize status Operation failed
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
test.t2 analyze status Table is already up to date
test.t3 analyze status Table is already up to date
-test.v1 analyze Error 'test.v1' is not BASE TABLE
+test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE'
test.v1 analyze status Operation failed
drop procedure bug13012|
drop view v1|
@@ -6469,7 +6469,7 @@ CALL p2(10);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `v` bigint(11) DEFAULT NULL
+ `v` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
@@ -6480,7 +6480,7 @@ Warning 1366 Incorrect integer value: 'text' for column 'v' at row 1
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `v` bigint(11) DEFAULT NULL
+ `v` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
@@ -6908,7 +6908,7 @@ drop procedure if exists p;
set @old_mode= @@sql_mode;
set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
select @@sql_mode into @full_mode;
-create procedure p() begin end;
+create procedure p() as begin end;
call p();
set @@sql_mode= @old_mode;
select replace(@full_mode, 'ALLOW_INVALID_DATES', 'INVALID_DATES') into @full_mode;
@@ -7823,6 +7823,7 @@ ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
show warnings;
Level Code Message
Error 1062 Duplicate entry '2' for key 'PRIMARY'
+Note 4070 At line 5 in test.p1
select * from t1;
id
1
@@ -8127,3 +8128,109 @@ v_name v_total
c 1
DROP PROCEDURE p1;
DROP TABLE t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12007 Allow ROW variables as a cursor FETCH target
+#
+# The cursor and the ROW variable in FETCH must have the same number of fields
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT FALSE;
+DECLARE rec ROW(aa INT, bb VARCHAR(32), cc INT);
+DECLARE cur CURSOR FOR SELECT 10 AS a,'b10' AS b;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+OPEN cur;
+read_loop:
+LOOP
+FETCH cur INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+ERROR HY000: Incorrect number of FETCH variables
+DROP PROCEDURE p1;
+# Multiple ROW variables in FETCH
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT FALSE;
+DECLARE rec1 ROW(aa INT);
+DECLARE rec2 ROW(aa INT);
+DECLARE cur CURSOR FOR SELECT 10 AS a, 20 AS b;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+OPEN cur;
+read_loop:
+LOOP
+FETCH cur INTO rec1, rec2;
+IF done THEN
+LEAVE read_loop;
+END IF;
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+# A complete working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT FALSE;
+DECLARE rec ROW(aa INT, bb VARCHAR(32));
+DECLARE cur CURSOR FOR SELECT a,b FROM t1;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+OPEN cur;
+read_loop:
+LOOP
+FETCH cur INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT CONCAT('rec=(',rec.aa,',',rec.bb,')') AS c;
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+c
+rec=(10,b10)
+c
+rec=(20,b20)
+c
+rec=(30,b30)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+# A ROW variable with a single field
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE done INT DEFAULT FALSE;
+DECLARE rec ROW(aa INT);
+DECLARE cur CURSOR FOR SELECT 10 AS a UNION SELECT 20;
+DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+OPEN cur;
+read_loop:
+LOOP
+FETCH cur INTO rec;
+IF done THEN
+LEAVE read_loop;
+END IF;
+SELECT CONCAT('rec=(',rec.aa,')') AS c;
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+c
+rec=(10)
+c
+rec=(20)
+DROP PROCEDURE p1;
diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result
index 4966418dbfd..9a8a5bd8f93 100644
--- a/mysql-test/r/status.result
+++ b/mysql-test/r/status.result
@@ -188,6 +188,7 @@ Variable_name Value
Created_tmp_disk_tables 0
Created_tmp_files 0
Created_tmp_tables 0
+Handler_tmp_delete 0
Handler_tmp_update 0
Handler_tmp_write 0
Rows_tmp_read 5
@@ -200,14 +201,15 @@ Variable_name Value
Created_tmp_disk_tables 0
Created_tmp_files 0
Created_tmp_tables 0
+Handler_tmp_delete 0
Handler_tmp_update 0
Handler_tmp_write 0
-Rows_tmp_read 13
+Rows_tmp_read 14
show status like 'com_show_status';
Variable_name Value
Com_show_status 8
rnd_diff tmp_table_diff
-28 8
+30 8
disconnect con1;
connection default;
flush status;
@@ -333,6 +335,7 @@ Handler_read_rnd_next 23
Handler_rollback 0
Handler_savepoint 0
Handler_savepoint_rollback 0
+Handler_tmp_delete 0
Handler_tmp_update 2
Handler_tmp_write 7
Handler_update 0
@@ -342,9 +345,10 @@ Variable_name Value
Created_tmp_disk_tables 1
Created_tmp_files 0
Created_tmp_tables 2
+Handler_tmp_delete 0
Handler_tmp_update 2
Handler_tmp_write 7
-Rows_tmp_read 43
+Rows_tmp_read 44
drop table t1;
CREATE TABLE t1 (i int(11) DEFAULT NULL, KEY i (i) ) ENGINE=MyISAM;
insert into t1 values (1),(2),(3),(4),(5);
@@ -376,6 +380,7 @@ Handler_read_rnd_next 2
Handler_rollback 0
Handler_savepoint 0
Handler_savepoint_rollback 0
+Handler_tmp_delete 0
Handler_tmp_update 0
Handler_tmp_write 2
Handler_update 0
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 3daaa633dfe..9f07b1fefff 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -27,7 +27,7 @@ NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
Note 1249 Select 4 was reduced during optimization
-Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
+Note 1003 /* select#1 */ select 1 AS `(SELECT 1)` union /* select#3 */ select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
@@ -39,7 +39,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (select 0 union select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
+Note 1003 /* select#1 */ select (/* select#3 */ select 0 union /* select#4 */ select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -57,7 +57,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from dual having (select 1) = 1
+Note 1003 /* select#1 */ select 1 AS `1` from dual having (/* select#3 */ select 1) = 1
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -198,7 +198,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
+Note 1003 (/* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (/* select#3 */ select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (/* select#4 */ select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -216,7 +216,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
+Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
set optimizer_switch=@tmp_optimizer_switch;
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
@@ -238,7 +238,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((select avg(`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
+Note 1003 /* select#1 */ select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((/* select#2 */ select avg(`test`.`t2`.`a` + (/* select#3 */ select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -284,7 +284,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -328,7 +328,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t2`.`a`>((select 2 from dual where 2 = `test`.`t2`.`a` union select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t2`.`a`>((/* select#2 */ select 2 from dual where 2 = `test`.`t2`.`a` union /* select#3 */ select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -381,7 +381,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
-Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
+Note 1003 /* select#1 */ select 'joce' AS `pseudo`,(/* select#2 */ select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -413,7 +413,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 100.00 Using where; Using index
Warnings:
-Note 1003 select (select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 /* select#1 */ select (/* select#2 */ select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -434,7 +434,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -566,7 +566,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 3 AS `numreponse` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 3 AS `numreponse` from `test`.`t1` where 1
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -607,11 +607,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b in (select b from t1);
-ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data
+affected rows: 3
+insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
a b
0 10
1 11
@@ -763,7 +764,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union /* select#3 */ select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -911,7 +912,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -926,7 +927,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1165,19 +1166,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1260,7 +1261,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) NOT NULL
+ `a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1272,7 +1273,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(select (select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#2 */ select (/* select#3 */ select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1326,7 +1327,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1336,7 +1337,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1381,7 +1382,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`)
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1614,25 +1615,25 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1647,7 +1648,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1655,7 +1656,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1666,7 +1667,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1674,7 +1675,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1682,7 +1683,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1690,7 +1691,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1698,7 +1699,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1706,7 +1707,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1717,7 +1718,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using temporary
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(/* select#2 */ select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1768,7 +1769,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION t1 system NULL NULL NULL NULL 1 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 'e' AS `s1` from dual where 1
+Note 1003 /* select#1 */ select 'e' AS `s1` from dual where 1
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1887,14 +1888,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null)))
+Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null)))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -2978,7 +2979,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -2991,7 +2992,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -4248,7 +4249,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `res`.`count(*)` AS `count(*)` from (select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
+Note 1003 /* select#1 */ select `res`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
DROP TABLE t1;
CREATE TABLE t1 (
a varchar(255) default NULL,
@@ -4457,7 +4458,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (/* select#3 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
DROP TABLE t1,t2;
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -4538,14 +4539,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
+Note 1003 /* select#1 */ select 1 AS `1` from <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT min(a) FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` where `test`.`t1`.`a` > 3 group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
+Note 1003 /* select#1 */ select 1 AS `1` from <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` where `test`.`t1`.`a` > 3 group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
SET join_cache_level=@save_join_cache_level;
DROP TABLE t1;
#
@@ -4636,7 +4637,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result
index b8295416e93..31e7774734e 100644
--- a/mysql-test/r/subselect2.result
+++ b/mysql-test/r/subselect2.result
@@ -262,7 +262,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2c ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (incremental, BNL join)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t2a`.`c2` from `test`.`t2` `t2a` join `test`.`t2` `t2b` join `test`.`t2` `t2c` where (`test`.`t2b`.`m` <> `test`.`t1`.`a` or `test`.`t2b`.`m` = `test`.`t2a`.`m`) and trigcond(<cache>(`test`.`t1`.`c1`) = `test`.`t2a`.`c2` or `test`.`t2a`.`c2` is null) and `test`.`t2c`.`c2` = `test`.`t2b`.`c2` and `test`.`t2b`.`n` = `test`.`t2a`.`m` having trigcond(`test`.`t2a`.`c2` is null))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t2a`.`c2` from `test`.`t2` `t2a` join `test`.`t2` `t2b` join `test`.`t2` `t2c` where (`test`.`t2b`.`m` <> `test`.`t1`.`a` or `test`.`t2b`.`m` = `test`.`t2a`.`m`) and trigcond(<cache>(`test`.`t1`.`c1`) = `test`.`t2a`.`c2` or `test`.`t2a`.`c2` is null) and `test`.`t2c`.`c2` = `test`.`t2b`.`c2` and `test`.`t2b`.`n` = `test`.`t2a`.`m` having trigcond(`test`.`t2a`.`c2` is null))))
DROP TABLE t1,t2;
#
# MDEV-614, also MDEV-536, also LP:1050806:
@@ -342,7 +342,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ref idx idx 6 func 2 100.00 Using where; Using index
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t3`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on(`test`.`t3`.`a` = `test`.`t1`.`a`) where `test`.`t1`.`a` = (select min(`test`.`t1`.`a`) from `test`.`t1`) and `test`.`t2`.`a` = (select min(`test`.`t1`.`a`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t3`.`a` AS `a` from `test`.`t1` join `test`.`t2` left join `test`.`t3` on(`test`.`t3`.`a` = `test`.`t1`.`a`) where `test`.`t1`.`a` = (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1`) and `test`.`t2`.`a` = (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1`)
select * from t1, t2 left join t3 on ( t2.a = t3.a )
where t1.a = t2.a and ( t1.a = ( select min(a) from t1 ) or 0 );
a a a
diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result
index 9ed067c0bdc..ca151daf146 100644
--- a/mysql-test/r/subselect3.result
+++ b/mysql-test/r/subselect3.result
@@ -33,7 +33,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `Z` from `test`.`t2`
explain extended
select a, oref from t2
where a in (select max(ie) from t1 where oref=t2.oref group by grp);
@@ -42,7 +42,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having <cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having <cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))
select a, oref, a in (
select max(ie) from t1 where oref=t2.oref group by grp union
select max(ie) from t1 where oref=t2.oref group by grp
@@ -73,7 +73,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary
Warnings:
-Note 1003 select <expr_cache><`test`.`t3`.`a`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = 4 group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t3`.`a`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = 4 group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
set @@optimizer_switch=@save_optimizer_switch;
drop table t1, t2, t3;
create table t1 (a int, oref int, key(a));
@@ -99,7 +99,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` having trigcond(`test`.`t1`.`a` is null))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` having trigcond(`test`.`t1`.`a` is null))))) AS `Z` from `test`.`t2`
flush status;
select oref, a from t2 where a in (select a from t1 where oref=t2.oref);
oref a
@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) and `test`.`t2`.`a` = `test`.`t1`.`b` having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3`
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) and `test`.`t2`.`a` = `test`.`t1`.`b` having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3`
drop table t1, t2, t3;
create table t1 (a int NOT NULL, b int NOT NULL, key(a));
insert into t1 values
@@ -197,7 +197,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) and `test`.`t2`.`a` = `test`.`t1`.`b`))) AS `Z` from `test`.`t3`
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) and `test`.`t2`.`a` = `test`.`t1`.`b`))) AS `Z` from `test`.`t3`
drop table t1,t2,t3;
create table t1 (oref int, grp int);
insert into t1 (oref, grp) values
@@ -221,7 +221,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select count(0) from `test`.`t1` group by `test`.`t1`.`grp` having `test`.`t1`.`grp` = `test`.`t2`.`oref` and trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(count(0)))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select count(0) from `test`.`t1` group by `test`.`t1`.`grp` having `test`.`t1`.`grp` = `test`.`t2`.`oref` and trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(count(0)))))) AS `Z` from `test`.`t2`
drop table t1, t2;
create table t1 (a int, b int, primary key (a));
insert into t1 values (1,1), (3,1),(100,1);
@@ -253,7 +253,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null))))) AS `Z` from `test`.`t2`
select a,b, oref, (a,b) in (select a,b from t1 where c=t2.oref) Z from t2;
a b oref Z
NULL 1 100 0
@@ -270,7 +270,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(select `test`.`t1`.`a`,`test`.`t1`.`b` from `test`.`t1` join `test`.`t4` where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null)))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(/* select#2 */ select `test`.`t1`.`a`,`test`.`t1`.`b` from `test`.`t1` join `test`.`t4` where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null)))) AS `Z` from `test`.`t2`
select a,b, oref,
(a,b) in (select a,b from t1,t4 where c=t2.oref) Z
from t2;
@@ -315,7 +315,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery idx idx 5 func 4 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2` where `test`.`t2`.`a` = 10 and `test`.`t2`.`b` = 10
+Note 1003 /* select#1 */ select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2` where `test`.`t2`.`a` = 10 and `test`.`t2`.`b` = 10
drop table t1, t2;
create table t1 (oref char(4), grp int, ie int);
insert into t1 (oref, grp, ie) values
@@ -585,7 +585,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery idx idx 5 func 4 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2`
drop table t1,t2;
create table t1 (oref char(4), grp int, ie int primary key);
insert into t1 (oref, grp, ie) values
@@ -716,7 +716,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 100.00 Using index
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t1`.`a` and !<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` where trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) having trigcond(`test`.`t1`.`a` is null))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t1`.`a` and !<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) having trigcond(`test`.`t1`.`a` is null))))
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1));
a
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1 WHERE a > 4));
@@ -1481,7 +1481,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
SELECT * FROM t1
WHERE (
( SELECT a FROM t2 WHERE a = 9 ),
@@ -1541,7 +1541,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t2.v' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`i` AS `i`,`test`.`t2`.`v` AS `v`,<expr_cache><`test`.`t2`.`v`>((select count(distinct `test`.`t1`.`i`) from `test`.`t1` where `test`.`t1`.`v` = `test`.`t2`.`v`)) AS `subsel` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`i` AS `i`,`test`.`t2`.`v` AS `v`,<expr_cache><`test`.`t2`.`v`>((/* select#2 */ select count(distinct `test`.`t1`.`i`) from `test`.`t1` where `test`.`t1`.`v` = `test`.`t2`.`v`)) AS `subsel` from `test`.`t2`
DROP TABLE t1,t2;
End of 5.6 tests
set @@optimizer_switch=@subselect3_tmp;
diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result
index 2a1fc0df957..adb3ec80394 100644
--- a/mysql-test/r/subselect3_jcl6.result
+++ b/mysql-test/r/subselect3_jcl6.result
@@ -43,7 +43,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `Z` from `test`.`t2`
explain extended
select a, oref from t2
where a in (select max(ie) from t1 where oref=t2.oref group by grp);
@@ -52,7 +52,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having <cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = `test`.`t2`.`oref` group by `test`.`t1`.`grp` having <cache>(`test`.`t2`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))
select a, oref, a in (
select max(ie) from t1 where oref=t2.oref group by grp union
select max(ie) from t1 where oref=t2.oref group by grp
@@ -83,7 +83,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary
Warnings:
-Note 1003 select <expr_cache><`test`.`t3`.`a`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = 4 group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t3`.`a`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where `test`.`t1`.`oref` = 4 group by `test`.`t1`.`grp` having trigcond(<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`)))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
set @@optimizer_switch=@save_optimizer_switch;
drop table t1, t2, t3;
create table t1 (a int, oref int, key(a));
@@ -109,7 +109,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` having trigcond(`test`.`t1`.`a` is null))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` having trigcond(`test`.`t1`.`a` is null))))) AS `Z` from `test`.`t2`
flush status;
select oref, a from t2 where a in (select a from t1 where oref=t2.oref);
oref a
@@ -179,7 +179,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) and `test`.`t2`.`a` = `test`.`t1`.`b` having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3`
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) and `test`.`t2`.`a` = `test`.`t1`.`b` having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3`
drop table t1, t2, t3;
create table t1 (a int NOT NULL, b int NOT NULL, key(a));
insert into t1 values
@@ -207,7 +207,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 100.00 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) and `test`.`t2`.`a` = `test`.`t1`.`b`))) AS `Z` from `test`.`t3`
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) and `test`.`t2`.`a` = `test`.`t1`.`b`))) AS `Z` from `test`.`t3`
drop table t1,t2,t3;
create table t1 (oref int, grp int);
insert into t1 (oref, grp) values
@@ -231,7 +231,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
Note 1276 Field or reference 't2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select count(0) from `test`.`t1` group by `test`.`t1`.`grp` having `test`.`t1`.`grp` = `test`.`t2`.`oref` and trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(count(0)))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`oref`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select count(0) from `test`.`t1` group by `test`.`t1`.`grp` having `test`.`t1`.`grp` = `test`.`t2`.`oref` and trigcond(<cache>(`test`.`t2`.`a`) = <ref_null_helper>(count(0)))))) AS `Z` from `test`.`t2`
drop table t1, t2;
create table t1 (a int, b int, primary key (a));
insert into t1 values (1,1), (3,1),(100,1);
@@ -263,7 +263,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a checking NULL where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null))))) AS `Z` from `test`.`t2`
select a,b, oref, (a,b) in (select a,b from t1 where c=t2.oref) Z from t2;
a b oref Z
NULL 1 100 0
@@ -280,7 +280,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(select `test`.`t1`.`a`,`test`.`t1`.`b` from `test`.`t1` join `test`.`t4` where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null)))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`oref` AS `oref`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(/* select#2 */ select `test`.`t1`.`a`,`test`.`t1`.`b` from `test`.`t1` join `test`.`t4` where `test`.`t1`.`c` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`b` or `test`.`t1`.`b` is null)) having trigcond(`test`.`t1`.`a` is null) and trigcond(`test`.`t1`.`b` is null)))) AS `Z` from `test`.`t2`
select a,b, oref,
(a,b) in (select a,b from t1,t4 where c=t2.oref) Z
from t2;
@@ -325,7 +325,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery idx idx 5 func 4 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2` where `test`.`t2`.`a` = 10 and `test`.`t2`.`b` = 10
+Note 1003 /* select#1 */ select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2` where `test`.`t2`.`a` = 10 and `test`.`t2`.`b` = 10
drop table t1, t2;
create table t1 (oref char(4), grp int, ie int);
insert into t1 (oref, grp, ie) values
@@ -595,7 +595,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index_subquery idx idx 5 func 4 100.00 Using where; Full scan on NULL key
Warnings:
Note 1276 Field or reference 'test.t2.oref' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`oref` AS `oref`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,<expr_cache><`test`.`t2`.`a`,`test`.`t2`.`b`,`test`.`t2`.`oref`>(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`b`),<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on idx checking NULL where `test`.`t1`.`oref` = `test`.`t2`.`oref` and trigcond(trigcond(<cache>(`test`.`t2`.`a`) = `test`.`t1`.`ie1` or `test`.`t1`.`ie1` is null)) and trigcond(trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`ie2` or `test`.`t1`.`ie2` is null)) having trigcond(`test`.`t1`.`ie1` is null) and trigcond(`test`.`t1`.`ie2` is null))))) AS `Z` from `test`.`t2`
drop table t1,t2;
create table t1 (oref char(4), grp int, ie int primary key);
insert into t1 (oref, grp, ie) values
@@ -726,7 +726,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 100.00 Using index
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t1`.`a` and !<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` where trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) having trigcond(`test`.`t1`.`a` is null))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t1`.`a` and !<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where trigcond(<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) having trigcond(`test`.`t1`.`a` is null))))
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1));
a
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1 WHERE a > 4));
@@ -1491,7 +1491,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
SELECT * FROM t1
WHERE (
( SELECT a FROM t2 WHERE a = 9 ),
@@ -1551,7 +1551,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t2.v' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`i` AS `i`,`test`.`t2`.`v` AS `v`,<expr_cache><`test`.`t2`.`v`>((select count(distinct `test`.`t1`.`i`) from `test`.`t1` where `test`.`t1`.`v` = `test`.`t2`.`v`)) AS `subsel` from `test`.`t2`
+Note 1003 /* select#1 */ select `test`.`t2`.`i` AS `i`,`test`.`t2`.`v` AS `v`,<expr_cache><`test`.`t2`.`v`>((/* select#2 */ select count(distinct `test`.`t1`.`i`) from `test`.`t1` where `test`.`t1`.`v` = `test`.`t2`.`v`)) AS `subsel` from `test`.`t2`
DROP TABLE t1,t2;
End of 5.6 tests
set @@optimizer_switch=@subselect3_tmp;
diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result
index 699a1b27b78..6126a7ed3f5 100644
--- a/mysql-test/r/subselect4.result
+++ b/mysql-test/r/subselect4.result
@@ -388,7 +388,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
-Note 1003 select (select 1 from `test`.`t2` where 0) AS `RESULT` from dual
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from `test`.`t2` where 0) AS `RESULT` from dual
first equivalent variant
SELECT (SELECT 1 FROM t2 WHERE d = IFNULL(c,NULL)) AS RESULT FROM t1 GROUP BY c ;
RESULT
@@ -399,7 +399,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
-Note 1003 select (select 1 from `test`.`t2` where 0) AS `RESULT` from dual group by NULL
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from `test`.`t2` where 0) AS `RESULT` from dual group by NULL
second equivalent variant
SELECT (SELECT 1 FROM t2 WHERE d = c) AS RESULT FROM t1 GROUP BY c ;
RESULT
@@ -410,7 +410,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
-Note 1003 select (select 1 from `test`.`t2` where 0) AS `RESULT` from dual group by NULL
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from `test`.`t2` where 0) AS `RESULT` from dual group by NULL
DROP TABLE t1,t2;
#
# BUG#45928 "Differing query results depending on MRR and
@@ -2349,7 +2349,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select 3 AS `f` from dual where !<expr_cache><3>(<in_optimizer>(3,<exists>(select `test`.`t1`.`b` from `test`.`t1` where (`test`.`t1`.`c` = 'USA' or `test`.`t1`.`c` <> 'USA') and trigcond(<cache>(3) = `test`.`t1`.`b` or `test`.`t1`.`b` is null) and `test`.`t1`.`b` = `test`.`t1`.`a` having trigcond(`test`.`t1`.`b` is null))))
+Note 1003 /* select#1 */ select 3 AS `f` from dual where !<expr_cache><3>(<in_optimizer>(3,<exists>(/* select#2 */ select `test`.`t1`.`b` from `test`.`t1` where (`test`.`t1`.`c` = 'USA' or `test`.`t1`.`c` <> 'USA') and trigcond(<cache>(3) = `test`.`t1`.`b` or `test`.`t1`.`b` is null) and `test`.`t1`.`b` = `test`.`t1`.`a` having trigcond(`test`.`t1`.`b` is null))))
SELECT * FROM t2
WHERE f NOT IN (SELECT b FROM t1
WHERE 0 OR (c IN ('USA') OR c NOT IN ('USA')) AND a = b);
diff --git a/mysql-test/r/subselect_cache.result b/mysql-test/r/subselect_cache.result
index 5c74555af00..813d668c88c 100644
--- a/mysql-test/r/subselect_cache.result
+++ b/mysql-test/r/subselect_cache.result
@@ -135,6 +135,7 @@ ANALYZE
{
"query_block": {
"select_id": 4,
+ "operation": "UNION",
"table": {
"message": "No tables used"
}
@@ -237,6 +238,7 @@ EXPLAIN
{
"query_block": {
"select_id": 4,
+ "operation": "UNION",
"table": {
"message": "No tables used"
}
@@ -3613,7 +3615,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`b` from `test`.`t2` where <cache>(`test`.`t1`.`a`) = `test`.`t2`.`b`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`b` from `test`.`t2` where <cache>(`test`.`t1`.`a`) = `test`.`t2`.`b`)))
drop table t1,t2;
set @@optimizer_switch= default;
# LP BUG#615760 (part 2: incorrect heap table index flags)
diff --git a/mysql-test/r/subselect_exists2in.result b/mysql-test/r/subselect_exists2in.result
index d5e61d4beca..8b525436c2f 100644
--- a/mysql-test/r/subselect_exists2in.result
+++ b/mysql-test/r/subselect_exists2in.result
@@ -68,7 +68,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t3 ALL bb NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t3`.`b` from `test`.`t3` where <cache>(`test`.`t1`.`a`) = `test`.`t3`.`b`))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t3`.`b` from `test`.`t3` where <cache>(`test`.`t1`.`a`) = `test`.`t3`.`b`))
-- EXIST2IN then MATERIALIZATION
set optimizer_switch='exists_to_in=on,in_to_exists=off,semijoin=off,materialization=on,subquery_cache=off';
SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t3 WHERE t3.b = t1.a);
@@ -81,7 +81,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t3`.`b` from `test`.`t3` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`b`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t3`.`b` from `test`.`t3` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`b`)))
-- NO EXIST2IN
set optimizer_switch='exists_to_in=off,subquery_cache=off';
SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t3 WHERE t3.b = t1.a);
@@ -94,7 +94,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t3 ALL bb NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where exists(select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`b` = `test`.`t1`.`a`)
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where exists(/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`b` = `test`.`t1`.`a`)
set optimizer_switch=default;
set optimizer_switch='exists_to_in=on';
drop table t1,t2,t3;
@@ -313,7 +313,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`b` from `test`.`t2` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`b`)))) or `test`.`t1`.`a` > 0
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`b` from `test`.`t2` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`b`)))) or `test`.`t1`.`a` > 0
drop tables t1,t2;
CREATE TABLE t1 ( a INT );
INSERT INTO t1 VALUES (1),(5);
@@ -330,7 +330,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t2.b' of SELECT #3 was resolved in SELECT #2
-Note 1003 select (select 1 from dual where !(1 is not null and <in_optimizer>(1,1 in ( <materialize> (select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` is not null ), <primary_index_lookup>(1 in <temporary table> on distinct_key where 1 = `<subquery3>`.`c`))))) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !(1 is not null and <in_optimizer>(1,1 in ( <materialize> (/* select#3 */ select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` is not null ), <primary_index_lookup>(1 in <temporary table> on distinct_key where 1 = `<subquery3>`.`c`))))) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1`
SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )
1
@@ -344,7 +344,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t2.b' of SELECT #3 was resolved in SELECT #2
-Note 1003 select (select 1 from dual where !(1 is not null and <in_optimizer>(1,1 in ( <materialize> (select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` is not null ), <primary_index_lookup>(1 in <temporary table> on distinct_key where 1 = `<subquery3>`.`c`))))) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !(1 is not null and <in_optimizer>(1,1 in ( <materialize> (/* select#3 */ select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` is not null ), <primary_index_lookup>(1 in <temporary table> on distinct_key where 1 = `<subquery3>`.`c`))))) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1`
SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )
1
@@ -358,7 +358,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t2.b' of SELECT #3 was resolved in SELECT #2
-Note 1003 select (select 1 from dual where !exists(select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` = 1)) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select 1 from dual where !exists(/* select#3 */ select `test`.`t3`.`c` from `test`.`t3` where `test`.`t3`.`c` = 1)) AS `( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )` from `test`.`t1`
SELECT ( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
( SELECT b FROM t2 WHERE NOT EXISTS ( SELECT c FROM t3 WHERE c = b ) )
1
@@ -401,7 +401,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`a1` AS `a1` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a1`),<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t3 on bb where <cache>(`test`.`t1`.`a`) = `test`.`t3`.`b` and <cache>(`test`.`t1`.`a1`) = `test`.`t3`.`b1`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`a1` AS `a1` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a1`),<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t3 on bb where <cache>(`test`.`t1`.`a`) = `test`.`t3`.`b` and <cache>(`test`.`t1`.`a1`) = `test`.`t3`.`b1`)))
-- EXIST2IN then MATERIALIZATION
set optimizer_switch='exists_to_in=on,in_to_exists=off,semijoin=off,materialization=on,subquery_cache=off';
SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t3 WHERE t3.b = t1.a and t3.b1 = t1.a1);
@@ -415,7 +415,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`a1` AS `a1` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a1`),(`test`.`t1`.`a`,`test`.`t1`.`a1`) in ( <materialize> (select `test`.`t3`.`b`,`test`.`t3`.`b1` from `test`.`t3` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`b` and `test`.`t1`.`a1` = `<subquery2>`.`b1`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`a1` AS `a1` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a1`),(`test`.`t1`.`a`,`test`.`t1`.`a1`) in ( <materialize> (/* select#2 */ select `test`.`t3`.`b`,`test`.`t3`.`b1` from `test`.`t3` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`b` and `test`.`t1`.`a1` = `<subquery2>`.`b1`)))
-- NO EXIST2IN
set optimizer_switch='exists_to_in=off,subquery_cache=off';
SELECT * FROM t1 WHERE EXISTS ( SELECT * FROM t3 WHERE t3.b = t1.a and t3.b1 = t1.a1);
@@ -429,7 +429,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`a1` AS `a1` from `test`.`t1` where exists(select 1 from `test`.`t3` where `test`.`t3`.`b` = `test`.`t1`.`a` and `test`.`t3`.`b1` = `test`.`t1`.`a1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`a1` AS `a1` from `test`.`t1` where exists(/* select#2 */ select 1 from `test`.`t3` where `test`.`t3`.`b` = `test`.`t1`.`a` and `test`.`t3`.`b1` = `test`.`t1`.`a1`)
set optimizer_switch=default;
set optimizer_switch='exists_to_in=on';
drop table t1,t3;
@@ -466,7 +466,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'v.d' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'v.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`c` AS `c` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`b`,<exists>(select `test`.`t2`.`b` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` <= `test`.`t2`.`d` and <cache>(`test`.`t2`.`b`) = `test`.`t2`.`b`)) and `test`.`t2`.`b` < 1
+Note 1003 /* select#1 */ select `test`.`t2`.`c` AS `c` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`b`,<exists>(/* select#2 */ select `test`.`t2`.`b` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` <= `test`.`t2`.`d` and <cache>(`test`.`t2`.`b`) = `test`.`t2`.`b`)) and `test`.`t2`.`b` < 1
set optimizer_switch=default;
set optimizer_switch='exists_to_in=on';
drop view v;
@@ -544,7 +544,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.alias2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.alias1.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`alias1`.`a` AS `a`,`test`.`alias1`.`b` AS `b`,`test`.`alias2`.`a` AS `a`,`test`.`alias2`.`b` AS `b` from `test`.`t1` `alias1` join `test`.`t1` `alias2` where <expr_cache><`test`.`alias1`.`b`,`test`.`alias2`.`a`>(<in_optimizer>(`test`.`alias1`.`b`,<exists>(select `test`.`t2`.`c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` <= `test`.`alias2`.`a` and <cache>(`test`.`alias1`.`b`) = `test`.`t2`.`c`))) or `test`.`alias1`.`a` = 'foo'
+Note 1003 /* select#1 */ select `test`.`alias1`.`a` AS `a`,`test`.`alias1`.`b` AS `b`,`test`.`alias2`.`a` AS `a`,`test`.`alias2`.`b` AS `b` from `test`.`t1` `alias1` join `test`.`t1` `alias2` where <expr_cache><`test`.`alias1`.`b`,`test`.`alias2`.`a`>(<in_optimizer>(`test`.`alias1`.`b`,<exists>(/* select#2 */ select `test`.`t2`.`c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` <= `test`.`alias2`.`a` and <cache>(`test`.`alias1`.`b`) = `test`.`t2`.`c`))) or `test`.`alias1`.`a` = 'foo'
drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch='exists_to_in=on';
@@ -568,7 +568,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where !(`test`.`t1`.`a` is not null and <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`b` from `test`.`t2` where `test`.`t2`.`b` is not null and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`b`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where !(`test`.`t1`.`a` is not null and <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`b` from `test`.`t2` where `test`.`t2`.`b` is not null and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`b`))))
drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch='exists_to_in=on';
@@ -608,7 +608,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.alias.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.alias.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`alias`.`a` AS `a`,`test`.`alias`.`b` AS `b` from `test`.`t1` `alias` where <in_optimizer>(`test`.`alias`.`b`,<exists>(select `test`.`t1`.`a` from `test`.`t1` where `test`.`t1`.`a` > `test`.`alias`.`a` and <cache>(`test`.`alias`.`b`) = `test`.`t1`.`a`))
+Note 1003 /* select#1 */ select `test`.`alias`.`a` AS `a`,`test`.`alias`.`b` AS `b` from `test`.`t1` `alias` where <in_optimizer>(`test`.`alias`.`b`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where `test`.`t1`.`a` > `test`.`alias`.`a` and <cache>(`test`.`alias`.`b`) = `test`.`t1`.`a`))
SET optimizer_switch = 'exists_to_in=on,materialization=on,semijoin=on';
SELECT * FROM t1 AS alias
WHERE EXISTS ( SELECT * FROM t1 WHERE a > alias.a AND a = alias.b );
@@ -661,7 +661,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.alias1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.alias2.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`alias1`.`a` AS `a`,`test`.`alias2`.`b` AS `b` from `test`.`t1` `alias1` join `test`.`t2` `alias2` where <expr_cache><`test`.`alias1`.`a`,`test`.`alias2`.`b`>(<in_optimizer>(`test`.`alias1`.`a`,<exists>(select `test`.`t2`.`b` from `test`.`t2` where `test`.`t2`.`b` > `test`.`alias2`.`b` and <cache>(`test`.`alias1`.`a`) = `test`.`t2`.`b`))) or `test`.`alias1`.`a` = 5
+Note 1003 /* select#1 */ select `test`.`alias1`.`a` AS `a`,`test`.`alias2`.`b` AS `b` from `test`.`t1` `alias1` join `test`.`t2` `alias2` where <expr_cache><`test`.`alias1`.`a`,`test`.`alias2`.`b`>(<in_optimizer>(`test`.`alias1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`b` from `test`.`t2` where `test`.`t2`.`b` > `test`.`alias2`.`b` and <cache>(`test`.`alias1`.`a`) = `test`.`t2`.`b`))) or `test`.`alias1`.`a` = 5
drop table t1, t2;
set optimizer_switch=default;
set optimizer_switch='exists_to_in=on';
@@ -905,7 +905,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'sq1.pk' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'sq1.f1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`,`test`.`t1`.`pk`>(exists(select 1 from `test`.`t1` `sq2` semi join (`test`.`t1`) where `test`.`sq2`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`pk` = `test`.`t1`.`f1`))
+Note 1003 /* select#1 */ select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`,`test`.`t1`.`pk`>(exists(/* select#3 */ select 1 from `test`.`t1` `sq2` semi join (`test`.`t1`) where `test`.`sq2`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`pk` = `test`.`t1`.`f1`))
SELECT STRAIGHT_JOIN sq1.f2
FROM ( SELECT * FROM t1 ) AS sq1
WHERE EXISTS ( SELECT * FROM t1 AS sq2
@@ -925,7 +925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'sq1.pk' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'sq1.f1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`f1`,<exists>(select `test`.`sq2`.`f1` from `test`.`t1` `sq2` semi join (`test`.`t1`) where `test`.`t1`.`pk` = `test`.`t1`.`f1` and <cache>(`test`.`t1`.`f1`) = `test`.`sq2`.`f1`)))
+Note 1003 /* select#1 */ select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`f1`,<exists>(/* select#3 */ select `test`.`sq2`.`f1` from `test`.`t1` `sq2` semi join (`test`.`t1`) where `test`.`t1`.`pk` = `test`.`t1`.`f1` and <cache>(`test`.`t1`.`f1`) = `test`.`sq2`.`f1`)))
SELECT STRAIGHT_JOIN sq1.f2
FROM ( SELECT * FROM t1 ) AS sq1
WHERE EXISTS ( SELECT * FROM t1 AS sq2
diff --git a/mysql-test/r/subselect_extra_no_semijoin.result b/mysql-test/r/subselect_extra_no_semijoin.result
index 8ed260cb31a..fc8d5759945 100644
--- a/mysql-test/r/subselect_extra_no_semijoin.result
+++ b/mysql-test/r/subselect_extra_no_semijoin.result
@@ -49,7 +49,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1276 Field or reference 'test.t1.cur_date' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 1 AS `id`,'2007-04-25 18:30:22' AS `cur_date` from dual where <expr_cache><1>(<in_optimizer>(1,<exists>(select `test`.`x1`.`id` from `test`.`t1` `x1` where 0)))
+Note 1003 /* select#1 */ select 1 AS `id`,'2007-04-25 18:30:22' AS `cur_date` from dual where <expr_cache><1>(<in_optimizer>(1,<exists>(/* select#2 */ select `test`.`x1`.`id` from `test`.`t1` `x1` where 0)))
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id cur_date
@@ -61,7 +61,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1276 Field or reference 'test.t2.cur_date' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 1 AS `id`,'2007-04-25' AS `cur_date` from dual where <expr_cache><1>(<in_optimizer>(1,<exists>(select `test`.`x1`.`id` from `test`.`t2` `x1` where 0)))
+Note 1003 /* select#1 */ select 1 AS `id`,'2007-04-25' AS `cur_date` from dual where <expr_cache><1>(<in_optimizer>(1,<exists>(/* select#2 */ select `test`.`x1`.`id` from `test`.`t2` `x1` where 0)))
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id cur_date
@@ -75,7 +75,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY x1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.cur_date' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`cur_date` AS `cur_date` from `test`.`t1` where <expr_cache><`test`.`t1`.`id`,`test`.`t1`.`cur_date`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(select `test`.`x1`.`id` from `test`.`t1` `x1` where `test`.`t1`.`cur_date` = 0 and <cache>(`test`.`t1`.`id`) = `test`.`x1`.`id`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`cur_date` AS `cur_date` from `test`.`t1` where <expr_cache><`test`.`t1`.`id`,`test`.`t1`.`cur_date`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(/* select#2 */ select `test`.`x1`.`id` from `test`.`t1` `x1` where `test`.`t1`.`cur_date` = 0 and <cache>(`test`.`t1`.`id`) = `test`.`x1`.`id`)))
select * from t1
where id in (select id from t1 as x1 where (t1.cur_date is null));
id cur_date
@@ -87,7 +87,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY x1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t2.cur_date' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t2`.`id` AS `id`,`test`.`t2`.`cur_date` AS `cur_date` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`,`test`.`t2`.`cur_date`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(select `test`.`x1`.`id` from `test`.`t2` `x1` where `test`.`t2`.`cur_date` = 0 and <cache>(`test`.`t2`.`id`) = `test`.`x1`.`id`)))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id`,`test`.`t2`.`cur_date` AS `cur_date` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`,`test`.`t2`.`cur_date`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select `test`.`x1`.`id` from `test`.`t2` `x1` where `test`.`t2`.`cur_date` = 0 and <cache>(`test`.`t2`.`id`) = `test`.`x1`.`id`)))
select * from t2
where id in (select id from t2 as x1 where (t2.cur_date is null));
id cur_date
@@ -351,7 +351,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
3 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where <cache>(0) = 0)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(/* select#3 */ select 0 from dual where <cache>(0) = 0)))
SELECT * FROM t2 RIGHT JOIN v1 AS t ON t.a != 0
WHERE t.a IN (SELECT b FROM t1);
a a b
@@ -364,7 +364,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where <cache>(0) = 0)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(/* select#2 */ select 0 from dual where <cache>(0) = 0)))
DROP VIEW v1;
DROP TABLE t1,t2;
#
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index bbcfa7d6980..350275d2463 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -50,7 +50,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1`))))
select * from t1 where a1 in (select b1 from t2 where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -61,7 +61,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1`))))
select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -72,7 +72,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`))))
select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -83,7 +83,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1`,min(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`b1` > '0' group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`min(b2)`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,min(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`b1` > '0' group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`min(b2)`))))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -94,7 +94,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index NULL _it1_idx # NULL 3 100.00 Using where;
2 MATERIALIZED t2i index it2i1,it2i3 it2i1 # NULL 5 100.00 Using where;
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`>(<in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select `test`.`t2i`.`b1` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`>(<in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1`))))
select * from t1i where a1 in (select b1 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -105,7 +105,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index NULL # 18 # 3 100.00 #
2 MATERIALIZED t2i range it2i1,it2i3 # 9 # 5 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`>(<in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (select max(`test`.`t2i`.`b1`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`max(b1)`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`>(<in_optimizer>(`test`.`t1i`.`a1`,`test`.`t1i`.`a1` in ( <materialize> (/* select#2 */ select max(`test`.`t2i`.`b1`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`max(b1)`))))
select * from t1i where a1 in (select max(b1) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -116,7 +116,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index NULL _it1_idx # NULL 3 100.00 Using where;
2 MATERIALIZED t2i index it2i1,it2i3 it2i3 # NULL 5 100.00 Using where;
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`b2`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`b2`))))
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
a1 a2
1 - 01 2 - 01
@@ -127,7 +127,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index NULL # # # 3 100.00 #
2 MATERIALIZED t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`max(b2)`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`max(b2)`))))
select * from t1i where (a1, a2) in (select b1, max(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -138,7 +138,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index NULL # # # 3 100.00 #
2 MATERIALIZED t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`min(b2)`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`min(b2)`))))
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -149,7 +149,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2i range NULL it2i3 9 NULL 3 100.00 Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`max(b2)`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`max(b2)`))))
select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1);
a1 a2
1 - 01 2 - 01
@@ -178,7 +178,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`min(b2)`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`min(b2)`))))
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -225,7 +225,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`))))
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -236,7 +236,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1i index NULL it1i3 18 NULL 3 100.00 Using where; Using index
2 MATERIALIZED t2i index NULL it2i3 18 NULL 5 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`b2`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2` ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`b2`))))
select * from t1i where (a1, a2) in (select b1, b2 from t2i order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -291,7 +291,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 MATERIALIZED t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery4>`.`b1` and `test`.`t3`.`c2` = `<subquery4>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery3>`.`c1` and `test`.`t1`.`a2` = `<subquery3>`.`c2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#3 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#4 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery4>`.`b1` and `test`.`t3`.`c2` = `<subquery4>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery3>`.`c1` and `test`.`t1`.`a2` = `<subquery3>`.`c2`))))
select * from t1
where (a1, a2) in (select b1, b2 from t2 where b1 > '0') and
(a1, a2) in (select c1, c2 from t3
@@ -310,7 +310,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 MATERIALIZED t2i index it2i2 # # # 5 100.00 #
2 MATERIALIZED t2i index it2i1,it2i3 # # # 5 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1`,`test`.`t3i`.`c2` from `test`.`t3i` where <expr_cache><`test`.`t3i`.`c1`,`test`.`t3i`.`c2`>(<in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key where `test`.`t3i`.`c1` = `<subquery4>`.`b1` and `test`.`t3i`.`c2` = `<subquery4>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery3>`.`c1` and `test`.`t1i`.`a2` = `<subquery3>`.`c2`))))
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery2>`.`b1` and `test`.`t1i`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#3 */ select `test`.`t3i`.`c1`,`test`.`t3i`.`c2` from `test`.`t3i` where <expr_cache><`test`.`t3i`.`c1`,`test`.`t3i`.`c2`>(<in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (/* select#4 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key where `test`.`t3i`.`c1` = `<subquery4>`.`b1` and `test`.`t3i`.`c2` = `<subquery4>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery3>`.`c1` and `test`.`t1i`.`a2` = `<subquery3>`.`c2`))))
select * from t1i
where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i
@@ -333,7 +333,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery6>`.`b1` and `test`.`t3`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#3 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#5 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#6 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery6>`.`b1` and `test`.`t3`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -358,7 +358,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key where `test`.`t3c`.`c1` = `<subquery6>`.`b1` and `test`.`t3c`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(/* select#3 */ select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#5 */ select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),(`test`.`t3c`.`c1`,`test`.`t3c`.`c2`) in ( <materialize> (/* select#6 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3c`.`c1` in <temporary table> on distinct_key where `test`.`t3c`.`c1` = `<subquery6>`.`b1` and `test`.`t3c`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
@@ -394,7 +394,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
8 MATERIALIZED t2i index it2i1,it2i3 # # # 5 100.00 #
NULL UNION RESULT <union1,7> ALL NULL # # # NULL NULL #
Warnings:
-Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery6>`.`b1` and `test`.`t3`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))) union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery8>`.`b1` and `test`.`t1i`.`a2` = `<subquery8>`.`b2`)))) and <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (select `test`.`t3i`.`c1`,`test`.`t3i`.`c2` from `test`.`t3i` where <expr_cache><`test`.`t3i`.`c1`,`test`.`t3i`.`c2`>(<in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key where `test`.`t3i`.`c1` = `<subquery10>`.`b1` and `test`.`t3i`.`c2` = `<subquery10>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery9>`.`c1` and `test`.`t1i`.`a2` = `<subquery9>`.`c2`)))))
+Note 1003 (/* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#3 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#5 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#6 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery6>`.`b1` and `test`.`t3`.`c2` = `<subquery6>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery5>`.`c1` and `test`.`t1`.`a2` = `<subquery5>`.`c2`))))) union (/* select#7 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` where <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#8 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery8>`.`b1` and `test`.`t1i`.`a2` = `<subquery8>`.`b2`)))) and <expr_cache><`test`.`t1i`.`a1`,`test`.`t1i`.`a2`>(<in_optimizer>((`test`.`t1i`.`a1`,`test`.`t1i`.`a2`),(`test`.`t1i`.`a1`,`test`.`t1i`.`a2`) in ( <materialize> (/* select#9 */ select `test`.`t3i`.`c1`,`test`.`t3i`.`c2` from `test`.`t3i` where <expr_cache><`test`.`t3i`.`c1`,`test`.`t3i`.`c2`>(<in_optimizer>((`test`.`t3i`.`c1`,`test`.`t3i`.`c2`),(`test`.`t3i`.`c1`,`test`.`t3i`.`c2`) in ( <materialize> (/* select#10 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3i`.`c1` in <temporary table> on distinct_key where `test`.`t3i`.`c1` = `<subquery10>`.`b1` and `test`.`t3i`.`c2` = `<subquery10>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1i`.`a1` in <temporary table> on distinct_key where `test`.`t1i`.`a1` = `<subquery9>`.`c1` and `test`.`t1i`.`a2` = `<subquery9>`.`c2`)))))
(select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -423,7 +423,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery5>`.`b1` and `test`.`t3`.`c2` = `<subquery5>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery4>`.`c1` and `test`.`t1`.`a2` = `<subquery4>`.`c2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#4 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#5 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery5>`.`b1` and `test`.`t3`.`c2` = `<subquery5>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery4>`.`c1` and `test`.`t1`.`a2` = `<subquery4>`.`c2`))))
select * from t1
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(a1, a2) in (select c1, c2 from t3
@@ -446,7 +446,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery5>`.`b1` and `test`.`t3`.`c2` = `<subquery5>`.`b2`)))) ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery4>`.`c1` and `test`.`t3`.`c2` = `<subquery4>`.`c2`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#4 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#5 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery5>`.`b1` and `test`.`t3`.`c2` = `<subquery5>`.`b2`)))) ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery4>`.`c1` and `test`.`t3`.`c2` = `<subquery4>`.`c2`))))
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -468,7 +468,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`>(<in_optimizer>(`test`.`t3`.`c1`,<exists>(select `test`.`t1`.`a1` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t3`.`c1`) = `test`.`t1`.`a1` union select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t3`.`c1`) = `test`.`t2`.`b1`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`>(<in_optimizer>(`test`.`t3`.`c1`,<exists>(/* select#2 */ select `test`.`t1`.`a1` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t3`.`c1`) = `test`.`t1`.`a1` union /* select#3 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t3`.`c1`) = `test`.`t2`.`b1`)))
select * from t3
where c1 in (select a1 from t1 where a1 > '0' UNION select b1 from t2 where b1 < '9');
c1 c2
@@ -492,14 +492,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (`test`.`t2i`.`b2` > '0' or `test`.`t2i`.`b2` = `test`.`t1`.`a2`) and <cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1` and <cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`)))) and <cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1` and <cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(/* select#3 */ select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#5 */ select `test`.`t3c`.`c1`,`test`.`t3c`.`c2` from `test`.`t3` `t3c` where <expr_cache><`test`.`t3c`.`c1`,`test`.`t3c`.`c2`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t3c`.`c1`,`test`.`t3c`.`c2`),<exists>(<index_lookup>(<cache>(`test`.`t3c`.`c1`) in t2i on it2i3 where (`test`.`t2i`.`b2` > '0' or `test`.`t2i`.`b2` = `test`.`t1`.`a2`) and <cache>(`test`.`t3c`.`c1`) = `test`.`t2i`.`b1` and <cache>(`test`.`t3c`.`c2`) = `test`.`t2i`.`b2`)))) and <cache>(`test`.`t1`.`a1`) = `test`.`t3c`.`c1` and <cache>(`test`.`t1`.`a2`) = `test`.`t3c`.`c2`)))
explain extended
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
a1 a2
1 - 01 2 - 01
@@ -509,7 +509,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01' from dual);
a1 a2
1 - 01 2 - 01
@@ -531,7 +531,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
2 SUBQUERY columns index NULL PRIMARY 4 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by (select `test`.`columns`.`col` from `test`.`columns` limit 1)
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by (/* select#2 */ select `test`.`columns`.`col` from `test`.`columns` limit 1)
select * from t1 group by (select col from columns limit 1);
a1 a2
1 - 00 2 - 00
@@ -541,7 +541,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using temporary; Using filesort
2 DEPENDENT SUBQUERY columns unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`a1`) in columns on PRIMARY where trigcond(<cache>(`test`.`t1`.`a1`) = `test`.`columns`.`col`)))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`a1`) in columns on PRIMARY where trigcond(<cache>(`test`.`t1`.`a1`) = `test`.`columns`.`col`)))))
select * from t1 group by (a1 in (select col from columns));
a1 a2
1 - 00 2 - 00
@@ -556,7 +556,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
2 SUBQUERY columns index NULL PRIMARY 4 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` order by (select `test`.`columns`.`col` from `test`.`columns` limit 1)
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` order by (/* select#2 */ select `test`.`columns`.`col` from `test`.`columns` limit 1)
select * from t1 order by (select col from columns limit 1);
a1 a2
1 - 00 2 - 00
@@ -602,7 +602,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,<exists>(select `test`.`t2_16`.`b1` from `test`.`t2_16` where `test`.`t2_16`.`b1` > '0' and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,<exists>(/* select#2 */ select `test`.`t2_16`.`b1` from `test`.`t2_16` where `test`.`t2_16`.`b1` > '0' and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1`)))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select b1 from t2_16 where b1 > '0');
@@ -616,7 +616,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`>(<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(select `test`.`t2_16`.`b1`,`test`.`t2_16`.`b2` from `test`.`t2_16` where `test`.`t2_16`.`b1` > '0' and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1` and <cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`>(<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(/* select#2 */ select `test`.`t2_16`.`b1`,`test`.`t2_16`.`b2` from `test`.`t2_16` where `test`.`t2_16`.`b1` > '0' and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1` and <cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`)))
select left(a1,7), left(a2,7)
from t1_16
where (a1,a2) in (select b1, b2 from t2_16 where b1 > '0');
@@ -630,7 +630,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select substr(`test`.`t2_16`.`b1`,1,16) from `test`.`t2_16` where `test`.`t2_16`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where `test`.`t1_16`.`a1` = `<subquery2>`.`substring(b1,1,16)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (/* select#2 */ select substr(`test`.`t2_16`.`b1`,1,16) from `test`.`t2_16` where `test`.`t2_16`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where `test`.`t1_16`.`a1` = `<subquery2>`.`substring(b1,1,16)`))))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select substring(b1,1,16) from t2_16 where b1 > '0');
@@ -644,7 +644,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,<exists>(select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2` having <cache>(`test`.`t1_16`.`a1`) = <ref_null_helper>(group_concat(`test`.`t2_16`.`b1` separator ',')))))
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,<exists>(/* select#2 */ select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2` having <cache>(`test`.`t1_16`.`a1`) = <ref_null_helper>(group_concat(`test`.`t2_16`.`b1` separator ',')))))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -659,7 +659,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2` ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where `test`.`t1_16`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,`test`.`t1_16`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2` ), <primary_index_lookup>(`test`.`t1_16`.`a1` in <temporary table> on distinct_key where `test`.`t1_16`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -681,7 +681,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><concat(`test`.`t1`.`a1`,'x')>(<in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(select left(`test`.`t1_16`.`a1`,8) from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`>(<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(select `test`.`t2_16`.`b1`,`test`.`t2_16`.`b2` from `test`.`t2_16` join `test`.`t2` where `test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6) and <expr_cache><`test`.`t2`.`b1`>(<in_optimizer>(`test`.`t2`.`b1`,`test`.`t2`.`b1` in ( <materialize> (select `test`.`t3`.`c1` from `test`.`t3` where `test`.`t3`.`c2` > '0' ), <primary_index_lookup>(`test`.`t2`.`b1` in <temporary table> on distinct_key where `test`.`t2`.`b1` = `<subquery4>`.`c1`)))) and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1` and <cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`))) and <cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><concat(`test`.`t1`.`a1`,'x')>(<in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(/* select#2 */ select left(`test`.`t1_16`.`a1`,8) from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`>(<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(/* select#3 */ select `test`.`t2_16`.`b1`,`test`.`t2_16`.`b2` from `test`.`t2_16` join `test`.`t2` where `test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6) and <expr_cache><`test`.`t2`.`b1`>(<in_optimizer>(`test`.`t2`.`b1`,`test`.`t2`.`b1` in ( <materialize> (/* select#4 */ select `test`.`t3`.`c1` from `test`.`t3` where `test`.`t3`.`c2` > '0' ), <primary_index_lookup>(`test`.`t2`.`b1` in <temporary table> on distinct_key where `test`.`t2`.`b1` = `<subquery4>`.`c1`)))) and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1` and <cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`))) and <cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8))))
drop table t1_16, t2_16, t3_16;
set @blob_len = 512;
set @suffix_len = @blob_len - @prefix_len;
@@ -715,7 +715,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,<exists>(select `test`.`t2_512`.`b1` from `test`.`t2_512` where `test`.`t2_512`.`b1` > '0' and <cache>(`test`.`t1_512`.`a1`) = `test`.`t2_512`.`b1`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,<exists>(/* select#2 */ select `test`.`t2_512`.`b1` from `test`.`t2_512` where `test`.`t2_512`.`b1` > '0' and <cache>(`test`.`t1_512`.`a1`) = `test`.`t2_512`.`b1`)))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select b1 from t2_512 where b1 > '0');
@@ -729,7 +729,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`,`test`.`t1_512`.`a2`>(<in_optimizer>((`test`.`t1_512`.`a1`,`test`.`t1_512`.`a2`),<exists>(select `test`.`t2_512`.`b1`,`test`.`t2_512`.`b2` from `test`.`t2_512` where `test`.`t2_512`.`b1` > '0' and <cache>(`test`.`t1_512`.`a1`) = `test`.`t2_512`.`b1` and <cache>(`test`.`t1_512`.`a2`) = `test`.`t2_512`.`b2`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`,`test`.`t1_512`.`a2`>(<in_optimizer>((`test`.`t1_512`.`a1`,`test`.`t1_512`.`a2`),<exists>(/* select#2 */ select `test`.`t2_512`.`b1`,`test`.`t2_512`.`b2` from `test`.`t2_512` where `test`.`t2_512`.`b1` > '0' and <cache>(`test`.`t1_512`.`a1`) = `test`.`t2_512`.`b1` and <cache>(`test`.`t1_512`.`a2`) = `test`.`t2_512`.`b2`)))
select left(a1,7), left(a2,7)
from t1_512
where (a1,a2) in (select b1, b2 from t2_512 where b1 > '0');
@@ -743,7 +743,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_512 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select substr(`test`.`t2_512`.`b1`,1,512) from `test`.`t2_512` where `test`.`t2_512`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where `test`.`t1_512`.`a1` = `<subquery2>`.`substring(b1,1,512)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (/* select#2 */ select substr(`test`.`t2_512`.`b1`,1,512) from `test`.`t2_512` where `test`.`t2_512`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where `test`.`t1_512`.`a1` = `<subquery2>`.`substring(b1,1,512)`))))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select substring(b1,1,512) from t2_512 where b1 > '0');
@@ -757,7 +757,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -774,7 +774,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_512 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from `test`.`t1_512` where <expr_cache><`test`.`t1_512`.`a1`>(<in_optimizer>(`test`.`t1_512`.`a1`,`test`.`t1_512`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2` ), <primary_index_lookup>(`test`.`t1_512`.`a1` in <temporary table> on distinct_key where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -816,7 +816,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,<exists>(select `test`.`t2_1024`.`b1` from `test`.`t2_1024` where `test`.`t2_1024`.`b1` > '0' and <cache>(`test`.`t1_1024`.`a1`) = `test`.`t2_1024`.`b1`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,<exists>(/* select#2 */ select `test`.`t2_1024`.`b1` from `test`.`t2_1024` where `test`.`t2_1024`.`b1` > '0' and <cache>(`test`.`t1_1024`.`a1`) = `test`.`t2_1024`.`b1`)))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select b1 from t2_1024 where b1 > '0');
@@ -830,7 +830,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a2`>(<in_optimizer>((`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a2`),<exists>(select `test`.`t2_1024`.`b1`,`test`.`t2_1024`.`b2` from `test`.`t2_1024` where `test`.`t2_1024`.`b1` > '0' and <cache>(`test`.`t1_1024`.`a1`) = `test`.`t2_1024`.`b1` and <cache>(`test`.`t1_1024`.`a2`) = `test`.`t2_1024`.`b2`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a2`>(<in_optimizer>((`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a2`),<exists>(/* select#2 */ select `test`.`t2_1024`.`b1`,`test`.`t2_1024`.`b2` from `test`.`t2_1024` where `test`.`t2_1024`.`b1` > '0' and <cache>(`test`.`t1_1024`.`a1`) = `test`.`t2_1024`.`b1` and <cache>(`test`.`t1_1024`.`a2`) = `test`.`t2_1024`.`b2`)))
select left(a1,7), left(a2,7)
from t1_1024
where (a1,a2) in (select b1, b2 from t2_1024 where b1 > '0');
@@ -844,7 +844,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,<exists>(select substr(`test`.`t2_1024`.`b1`,1,1024) from `test`.`t2_1024` where `test`.`t2_1024`.`b1` > '0' and <cache>(`test`.`t1_1024`.`a1`) = substr(`test`.`t2_1024`.`b1`,1,1024))))
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,<exists>(/* select#2 */ select substr(`test`.`t2_1024`.`b1`,1,1024) from `test`.`t2_1024` where `test`.`t2_1024`.`b1` > '0' and <cache>(`test`.`t1_1024`.`a1`) = substr(`test`.`t2_1024`.`b1`,1,1024))))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select substring(b1,1,1024) from t2_1024 where b1 > '0');
@@ -858,7 +858,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -875,7 +875,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1024 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1024` where <expr_cache><`test`.`t1_1024`.`a1`>(<in_optimizer>(`test`.`t1_1024`.`a1`,`test`.`t1_1024`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2` ), <primary_index_lookup>(`test`.`t1_1024`.`a1` in <temporary table> on distinct_key where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -917,7 +917,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,<exists>(select `test`.`t2_1025`.`b1` from `test`.`t2_1025` where `test`.`t2_1025`.`b1` > '0' and <cache>(`test`.`t1_1025`.`a1`) = `test`.`t2_1025`.`b1`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,<exists>(/* select#2 */ select `test`.`t2_1025`.`b1` from `test`.`t2_1025` where `test`.`t2_1025`.`b1` > '0' and <cache>(`test`.`t1_1025`.`a1`) = `test`.`t2_1025`.`b1`)))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select b1 from t2_1025 where b1 > '0');
@@ -931,7 +931,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a2`>(<in_optimizer>((`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a2`),<exists>(select `test`.`t2_1025`.`b1`,`test`.`t2_1025`.`b2` from `test`.`t2_1025` where `test`.`t2_1025`.`b1` > '0' and <cache>(`test`.`t1_1025`.`a1`) = `test`.`t2_1025`.`b1` and <cache>(`test`.`t1_1025`.`a2`) = `test`.`t2_1025`.`b2`)))
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a2`>(<in_optimizer>((`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a2`),<exists>(/* select#2 */ select `test`.`t2_1025`.`b1`,`test`.`t2_1025`.`b2` from `test`.`t2_1025` where `test`.`t2_1025`.`b1` > '0' and <cache>(`test`.`t1_1025`.`a1`) = `test`.`t2_1025`.`b1` and <cache>(`test`.`t1_1025`.`a2`) = `test`.`t2_1025`.`b2`)))
select left(a1,7), left(a2,7)
from t1_1025
where (a1,a2) in (select b1, b2 from t2_1025 where b1 > '0');
@@ -945,7 +945,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,<exists>(select substr(`test`.`t2_1025`.`b1`,1,1025) from `test`.`t2_1025` where `test`.`t2_1025`.`b1` > '0' and <cache>(`test`.`t1_1025`.`a1`) = substr(`test`.`t2_1025`.`b1`,1,1025))))
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,<exists>(/* select#2 */ select substr(`test`.`t2_1025`.`b1`,1,1025) from `test`.`t2_1025` where `test`.`t2_1025`.`b1` > '0' and <cache>(`test`.`t1_1025`.`a1`) = substr(`test`.`t2_1025`.`b1`,1,1025))))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select substring(b1,1,1025) from t2_1025 where b1 > '0');
@@ -959,7 +959,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -976,7 +976,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_1025 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`))))
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from `test`.`t1_1025` where <expr_cache><`test`.`t1_1025`.`a1`>(<in_optimizer>(`test`.`t1_1025`.`a1`,`test`.`t1_1025`.`a1` in ( <materialize> (/* select#2 */ select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2` ), <primary_index_lookup>(`test`.`t1_1025`.`a1` in <temporary table> on distinct_key where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`))))
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -1001,7 +1001,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1bit ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t2bit ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from `test`.`t1bit` where <expr_cache><`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`>(<in_optimizer>((`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`),(`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`) in ( <materialize> (select `test`.`t2bit`.`b1`,`test`.`t2bit`.`b2` from `test`.`t2bit` ), <primary_index_lookup>(`test`.`t1bit`.`a1` in <temporary table> on distinct_key where `test`.`t1bit`.`a1` = `<subquery2>`.`b1` and `test`.`t1bit`.`a2` = `<subquery2>`.`b2`))))
+Note 1003 /* select#1 */ select conv(`test`.`t1bit`.`a1`,10,2) AS `bin(a1)`,conv(`test`.`t1bit`.`a2`,10,2) AS `bin(a2)` from `test`.`t1bit` where <expr_cache><`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`>(<in_optimizer>((`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`),(`test`.`t1bit`.`a1`,`test`.`t1bit`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2bit`.`b1`,`test`.`t2bit`.`b2` from `test`.`t2bit` ), <primary_index_lookup>(`test`.`t1bit`.`a1` in <temporary table> on distinct_key where `test`.`t1bit`.`a1` = `<subquery2>`.`b1` and `test`.`t1bit`.`a2` = `<subquery2>`.`b2`))))
select bin(a1), bin(a2)
from t1bit
where (a1, a2) in (select b1, b2 from t2bit);
@@ -1024,7 +1024,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1bb ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2bb ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select conv(`test`.`t1bb`.`a1`,10,2) AS `bin(a1)`,`test`.`t1bb`.`a2` AS `a2` from `test`.`t1bb` where <expr_cache><`test`.`t1bb`.`a1`,`test`.`t1bb`.`a2`>(<in_optimizer>((`test`.`t1bb`.`a1`,`test`.`t1bb`.`a2`),<exists>(select `test`.`t2bb`.`b1`,`test`.`t2bb`.`b2` from `test`.`t2bb` where <cache>(`test`.`t1bb`.`a1`) = `test`.`t2bb`.`b1` and <cache>(`test`.`t1bb`.`a2`) = `test`.`t2bb`.`b2`)))
+Note 1003 /* select#1 */ select conv(`test`.`t1bb`.`a1`,10,2) AS `bin(a1)`,`test`.`t1bb`.`a2` AS `a2` from `test`.`t1bb` where <expr_cache><`test`.`t1bb`.`a1`,`test`.`t1bb`.`a2`>(<in_optimizer>((`test`.`t1bb`.`a1`,`test`.`t1bb`.`a2`),<exists>(/* select#2 */ select `test`.`t2bb`.`b1`,`test`.`t2bb`.`b2` from `test`.`t2bb` where <cache>(`test`.`t1bb`.`a1`) = `test`.`t2bb`.`b1` and <cache>(`test`.`t1bb`.`a2`) = `test`.`t2bb`.`b2`)))
select bin(a1), a2
from t1bb
where (a1, a2) in (select b1, b2 from t2bb);
@@ -1072,7 +1072,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1086,7 +1086,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using where; Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1100,7 +1100,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using where; Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1113,7 +1113,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1125,7 +1125,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1140,7 +1140,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
Note 1981 Aggregate function 'max()' of SELECT #3 belongs to SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`c` from `test`.`t2` where <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where max(`test`.`t1`.`b`) = `test`.`t3`.`e` having <cache>(`test`.`t2`.`d`) >= <ref_null_helper>(`test`.`t3`.`e`))))) and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`c`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where max(`test`.`t1`.`b`) = `test`.`t3`.`e` having <cache>(`test`.`t2`.`d`) >= <ref_null_helper>(`test`.`t3`.`e`))))) and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`c`)))
select a from t1 group by a
having a in (select c from t2 where d >= some(select e from t3 where max(b)=e));
a
@@ -1155,7 +1155,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`c` from `test`.`t2` where <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`)))) and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`c`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`)))) and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`c`)))
select a from t1
where a in (select c from t2 where d >= some(select e from t3 where b=e));
a
@@ -1824,7 +1824,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 8 AS `a` from dual where <expr_cache><8>(<in_optimizer>(8,<exists>(select min(`test`.`t1`.`a`) from `test`.`t1` having <cache>(8) = <ref_null_helper>(min(`test`.`t1`.`a`)))))
+Note 1003 /* select#1 */ select 8 AS `a` from dual where <expr_cache><8>(<in_optimizer>(8,<exists>(/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` having <cache>(8) = <ref_null_helper>(min(`test`.`t1`.`a`)))))
DROP TABLE t1;
#
# BUG#904432: Wrong result with LEFT JOIN, constant table, semijoin=ON,materialization=ON
@@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
SELECT * FROM t1
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
a b
@@ -2251,7 +2251,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 8 100.00
Warnings:
Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`f1` = `test`.`t3`.`f3`))
+Note 1003 /* select#1 */ select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`>(exists(/* select#2 */ select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`f1` = `test`.`t3`.`f3`))
# this checks the result set above
set optimizer_switch= 'materialization=off,semijoin=off';
SELECT * FROM t1
@@ -2289,7 +2289,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`f1` AS `f1`,<expr_cache><`test`.`t1`.`pk`>((select count(0) from `test`.`t2` semi join (`test`.`t2`) where `test`.`t1`.`pk` = `test`.`t2`.`f2`)) AS `sq` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`f1` AS `f1`,<expr_cache><`test`.`t1`.`pk`>((/* select#2 */ select count(0) from `test`.`t2` semi join (`test`.`t2`) where `test`.`t1`.`pk` = `test`.`t2`.`f2`)) AS `sq` from `test`.`t1`
# this checks the result set above
set @save_optimizer_switch= @@optimizer_switch;
set optimizer_switch= 'materialization=off,semijoin=off';
@@ -2711,7 +2711,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select max(`test`.`t1`.`b`) AS `max_res` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select max(`test`.`t1`.`b`) AS `max_res` from `test`.`t1` where 0
set @@optimizer_switch='materialization=off,in_to_exists=on,semijoin=off';
SELECT MAX(t1.b) AS max_res FROM t1 WHERE (9) IN (SELECT a FROM t2);
max_res
@@ -2722,7 +2722,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select max(`test`.`t1`.`b`) AS `max_res` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select max(`test`.`t1`.`b`) AS `max_res` from `test`.`t1` where 0
DROP TABLE t1,t2;
#
# LPBUG#825095: Wrong result with materialization and NOT IN with 2 expressions
diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result
index bdbe07cf879..68e664c2a22 100644
--- a/mysql-test/r/subselect_mat_cost_bugs.result
+++ b/mysql-test/r/subselect_mat_cost_bugs.result
@@ -100,7 +100,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 index c3 c3 9 NULL 2 100.00 Using where; Using index; Using join buffer (flat, BNL join)
Warnings:
Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where <expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t1a`.`c1` from `test`.`t1b` join `test`.`t2` left join `test`.`t1a` on(`test`.`t1a`.`c2` = `test`.`t1b`.`pk` and 2) where `test`.`t1`.`pk` <> 0 and <cache>(`test`.`t1`.`c1`) = `test`.`t1a`.`c1` and `test`.`t2`.`c3` = `test`.`t1b`.`c4`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where <expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t1a`.`c1` from `test`.`t1b` join `test`.`t2` left join `test`.`t1a` on(`test`.`t1a`.`c2` = `test`.`t1b`.`pk` and 2) where `test`.`t1`.`pk` <> 0 and <cache>(`test`.`t1`.`c1`) = `test`.`t1a`.`c1` and `test`.`t2`.`c3` = `test`.`t1b`.`c4`)))
SELECT pk
FROM t1
WHERE c1 IN
@@ -460,7 +460,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t1 index NULL a 5 NULL 2 100.00 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,`test`.`t2`.`b` in ( <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where `test`.`t2`.`c` = `test`.`t2`.`b` ), <primary_index_lookup>(`test`.`t2`.`b` in <temporary table> on distinct_key where `test`.`t2`.`b` = `<subquery2>`.`MIN(a)`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,`test`.`t2`.`b` in ( <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where `test`.`t2`.`c` = `test`.`t2`.`b` ), <primary_index_lookup>(`test`.`t2`.`b` in <temporary table> on distinct_key where `test`.`t2`.`b` = `<subquery2>`.`MIN(a)`))))
set optimizer_switch= 'materialization=off';
SELECT * FROM t2 WHERE b != ALL (SELECT MIN(a) FROM t1, t2 WHERE t2.c = t2.b);
b c
@@ -470,7 +470,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 index NULL a 5 NULL 2 100.00 Using index
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where `test`.`t2`.`c` = `test`.`t2`.`b` having trigcond(<cache>(`test`.`t2`.`b`) = <ref_null_helper>(min(`test`.`t1`.`a`))))))
+Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` join `test`.`t2` where `test`.`t2`.`c` = `test`.`t2`.`b` having trigcond(<cache>(`test`.`t2`.`b`) = <ref_null_helper>(min(`test`.`t1`.`a`))))))
set optimizer_switch= @optimizer_switch_save;
DROP TABLE t1,t2;
CREATE TABLE t1 (f1 varchar(10)) ENGINE=MyISAM;
diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result
index 2a0f542be19..e4b57d96b38 100644
--- a/mysql-test/r/subselect_no_exists_to_in.result
+++ b/mysql-test/r/subselect_no_exists_to_in.result
@@ -31,7 +31,7 @@ NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
Note 1249 Select 4 was reduced during optimization
-Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
+Note 1003 /* select#1 */ select 1 AS `(SELECT 1)` union /* select#3 */ select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
@@ -43,7 +43,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (select 0 union select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
+Note 1003 /* select#1 */ select (/* select#3 */ select 0 union /* select#4 */ select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -61,7 +61,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from dual having (select 1) = 1
+Note 1003 /* select#1 */ select 1 AS `1` from dual having (/* select#3 */ select 1) = 1
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -202,7 +202,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
+Note 1003 (/* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (/* select#3 */ select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (/* select#4 */ select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -220,7 +220,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
+Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
set optimizer_switch=@tmp_optimizer_switch;
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
@@ -242,7 +242,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((select avg(`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
+Note 1003 /* select#1 */ select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((/* select#2 */ select avg(`test`.`t2`.`a` + (/* select#3 */ select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -288,7 +288,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -332,7 +332,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t2`.`a`>((select 2 from dual where 2 = `test`.`t2`.`a` union select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t2`.`a`>((/* select#2 */ select 2 from dual where 2 = `test`.`t2`.`a` union /* select#3 */ select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -350,7 +350,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where <expr_cache><`test`.`t6`.`clinic_uq`>(exists(select 1 from `test`.`t7` where `test`.`t7`.`uq` = `test`.`t6`.`clinic_uq`))
+Note 1003 /* select#1 */ select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where <expr_cache><`test`.`t6`.`clinic_uq`>(exists(/* select#2 */ select 1 from `test`.`t7` where `test`.`t7`.`uq` = `test`.`t6`.`clinic_uq`))
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
ERROR 23000: Column 'a' in field list is ambiguous
drop table t1,t2,t3;
@@ -385,7 +385,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
-Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
+Note 1003 /* select#1 */ select 'joce' AS `pseudo`,(/* select#2 */ select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -417,7 +417,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 100.00 Using where; Using index
Warnings:
-Note 1003 select (select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 /* select#1 */ select (/* select#2 */ select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -438,7 +438,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -570,7 +570,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 3 AS `numreponse` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 3 AS `numreponse` from `test`.`t1` where 1
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -611,11 +611,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b in (select b from t1);
-ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data
+affected rows: 3
+insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
a b
0 10
1 11
@@ -767,7 +768,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union /* select#3 */ select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -915,7 +916,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -930,7 +931,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1169,19 +1170,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1264,7 +1265,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) NOT NULL
+ `a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1276,7 +1277,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(select (select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#2 */ select (/* select#3 */ select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1330,7 +1331,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1340,7 +1341,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1385,7 +1386,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`)
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1618,25 +1619,25 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1651,7 +1652,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1659,7 +1660,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1670,7 +1671,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1678,7 +1679,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1686,7 +1687,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1694,7 +1695,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1702,7 +1703,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1710,7 +1711,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1721,7 +1722,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using temporary
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(/* select#2 */ select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1772,7 +1773,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION t1 system NULL NULL NULL NULL 1 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 'e' AS `s1` from dual where 1
+Note 1003 /* select#1 */ select 'e' AS `s1` from dual where 1
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1891,14 +1892,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<expr_cache><`test`.`tt`.`id`>(exists(select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null))
+Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -2434,7 +2435,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.up.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where <expr_cache><`test`.`up`.`a`>(exists(select 1 from `test`.`t1` where `test`.`t1`.`a` = `test`.`up`.`a`))
+Note 1003 /* select#1 */ select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where <expr_cache><`test`.`up`.`a`>(exists(/* select#2 */ select 1 from `test`.`t1` where `test`.`t1`.`a` = `test`.`up`.`a`))
drop table t1;
CREATE TABLE t1 (t1_a int);
INSERT INTO t1 VALUES (1);
@@ -2981,7 +2982,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -2994,7 +2995,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -4251,7 +4252,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `res`.`count(*)` AS `count(*)` from (select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
+Note 1003 /* select#1 */ select `res`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
DROP TABLE t1;
CREATE TABLE t1 (
a varchar(255) default NULL,
@@ -4447,7 +4448,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists(select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists(/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
(SELECT 1 FROM t2 WHERE t1.a = t2.a));
@@ -4459,7 +4460,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (/* select#3 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
DROP TABLE t1,t2;
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -4540,14 +4541,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
+Note 1003 /* select#1 */ select 1 AS `1` from <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT min(a) FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` where `test`.`t1`.`a` > 3 group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
+Note 1003 /* select#1 */ select 1 AS `1` from <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` where `test`.`t1`.`a` > 3 group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
SET join_cache_level=@save_join_cache_level;
DROP TABLE t1;
#
@@ -4638,7 +4639,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index c941f924e21..22082774668 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -34,7 +34,7 @@ NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
Note 1249 Select 4 was reduced during optimization
-Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
+Note 1003 /* select#1 */ select 1 AS `(SELECT 1)` union /* select#3 */ select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
@@ -46,7 +46,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (select 0 union select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
+Note 1003 /* select#1 */ select (/* select#3 */ select 0 union /* select#4 */ select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -64,7 +64,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from dual having (select 1) = 1
+Note 1003 /* select#1 */ select 1 AS `1` from dual having (/* select#3 */ select 1) = 1
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -205,7 +205,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
+Note 1003 (/* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (/* select#3 */ select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (/* select#4 */ select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -223,7 +223,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
+Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
set optimizer_switch=@tmp_optimizer_switch;
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
@@ -245,7 +245,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((select avg(`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
+Note 1003 /* select#1 */ select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((/* select#2 */ select avg(`test`.`t2`.`a` + (/* select#3 */ select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -291,7 +291,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -335,7 +335,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t2`.`a`>((select 2 from dual where 2 = `test`.`t2`.`a` union select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t2`.`a`>((/* select#2 */ select 2 from dual where 2 = `test`.`t2`.`a` union /* select#3 */ select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -388,7 +388,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
-Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
+Note 1003 /* select#1 */ select 'joce' AS `pseudo`,(/* select#2 */ select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -420,7 +420,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 100.00 Using where; Using index
Warnings:
-Note 1003 select (select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 /* select#1 */ select (/* select#2 */ select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -441,7 +441,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -573,7 +573,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 3 AS `numreponse` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 3 AS `numreponse` from `test`.`t1` where 1
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -614,11 +614,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b in (select b from t1);
-ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data
+affected rows: 3
+insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
a b
0 10
1 11
@@ -770,7 +771,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union /* select#3 */ select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -918,7 +919,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -933,7 +934,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1172,19 +1173,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1267,7 +1268,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) NOT NULL
+ `a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1279,7 +1280,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(select (select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#2 */ select (/* select#3 */ select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1333,7 +1334,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1343,7 +1344,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1388,7 +1389,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`)
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1621,25 +1622,25 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1654,7 +1655,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1662,7 +1663,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1673,7 +1674,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1681,7 +1682,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1689,7 +1690,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1697,7 +1698,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1705,7 +1706,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1713,7 +1714,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1724,7 +1725,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using temporary
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(/* select#2 */ select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1775,7 +1776,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION t1 system NULL NULL NULL NULL 1 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 'e' AS `s1` from dual where 1
+Note 1003 /* select#1 */ select 'e' AS `s1` from dual where 1
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1894,14 +1895,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null)))
+Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null)))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -2984,7 +2985,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -2996,7 +2997,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null)))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -4251,7 +4252,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `res`.`count(*)` AS `count(*)` from (select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
+Note 1003 /* select#1 */ select `res`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
DROP TABLE t1;
CREATE TABLE t1 (
a varchar(255) default NULL,
@@ -4459,7 +4460,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (/* select#3 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
DROP TABLE t1,t2;
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -4539,13 +4540,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT min(a) FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 0
SET join_cache_level=@save_join_cache_level;
DROP TABLE t1;
#
@@ -4636,7 +4637,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index 2aebdd6c82d..5f71700c4ce 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -30,7 +30,7 @@ NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
Note 1249 Select 4 was reduced during optimization
-Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
+Note 1003 /* select#1 */ select 1 AS `(SELECT 1)` union /* select#3 */ select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
@@ -42,7 +42,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (select 0 union select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
+Note 1003 /* select#1 */ select (/* select#3 */ select 0 union /* select#4 */ select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -60,7 +60,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from dual having (select 1) = 1
+Note 1003 /* select#1 */ select 1 AS `1` from dual having (/* select#3 */ select 1) = 1
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -201,7 +201,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
+Note 1003 (/* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (/* select#3 */ select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (/* select#4 */ select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -219,7 +219,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
+Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
set optimizer_switch=@tmp_optimizer_switch;
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
@@ -241,7 +241,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t4`.`b` AS `b`,(select avg(`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
+Note 1003 /* select#1 */ select `test`.`t4`.`b` AS `b`,(/* select#2 */ select avg(`test`.`t2`.`a` + (/* select#3 */ select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -287,7 +287,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -331,7 +331,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select (select 2 from dual where 2 = `test`.`t2`.`a` union select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
+Note 1003 /* select#1 */ select (/* select#2 */ select 2 from dual where 2 = `test`.`t2`.`a` union /* select#3 */ select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -349,7 +349,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t7 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where <in_optimizer>(`test`.`t6`.`clinic_uq`,<exists>(<primary_index_lookup>(<cache>(`test`.`t6`.`clinic_uq`) in t7 on PRIMARY)))
+Note 1003 /* select#1 */ select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where <in_optimizer>(`test`.`t6`.`clinic_uq`,<exists>(<primary_index_lookup>(<cache>(`test`.`t6`.`clinic_uq`) in t7 on PRIMARY)))
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
ERROR 23000: Column 'a' in field list is ambiguous
drop table t1,t2,t3;
@@ -384,7 +384,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
-Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
+Note 1003 /* select#1 */ select 'joce' AS `pseudo`,(/* select#2 */ select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -416,7 +416,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 100.00 Using where; Using index
Warnings:
-Note 1003 select (select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 /* select#1 */ select (/* select#2 */ select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -437,7 +437,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -569,7 +569,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 3 AS `numreponse` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 3 AS `numreponse` from `test`.`t1` where 1
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -610,11 +610,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b in (select b from t1);
-ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data
+affected rows: 3
+insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
a b
0 10
1 11
@@ -766,7 +767,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3)))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union /* select#3 */ select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3)))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -914,7 +915,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -929,7 +930,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null)) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null)) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1168,19 +1169,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1263,7 +1264,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) NOT NULL
+ `a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1275,7 +1276,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(select (select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#2 */ select (/* select#3 */ select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1329,7 +1330,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1339,7 +1340,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1384,7 +1385,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`)
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1446,7 +1447,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY)))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1456,7 +1457,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1467,7 +1468,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 100.00 Using where
2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t1`.`b` and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t1`.`b` and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1489,7 +1490,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a)))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1499,7 +1500,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1510,7 +1511,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1167 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`a` and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`a` and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1526,7 +1527,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
drop table t0, t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -1617,25 +1618,25 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1650,7 +1651,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1658,7 +1659,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1669,7 +1670,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1677,7 +1678,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1685,7 +1686,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1693,7 +1694,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1701,7 +1702,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1709,7 +1710,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1720,7 +1721,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using temporary
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(/* select#2 */ select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1771,7 +1772,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION t1 system NULL NULL NULL NULL 1 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 'e' AS `s1` from dual where 1
+Note 1003 /* select#1 */ select 'e' AS `s1` from dual where 1
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1890,14 +1891,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,exists(select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null))
+Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -2433,7 +2434,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.up.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where <in_optimizer>(`test`.`up`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` where <cache>(`test`.`up`.`a`) = `test`.`t1`.`a`))
+Note 1003 /* select#1 */ select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where <in_optimizer>(`test`.`up`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where <cache>(`test`.`up`.`a`) = `test`.`t1`.`a`))
drop table t1;
CREATE TABLE t1 (t1_a int);
INSERT INTO t1 VALUES (1);
@@ -2980,19 +2981,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = 'N' and <cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` and <cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`))
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = 'N' and <cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` and <cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -4247,7 +4248,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `res`.`count(*)` AS `count(*)` from (select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
+Note 1003 /* select#1 */ select `res`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
DROP TABLE t1;
CREATE TABLE t1 (
a varchar(255) default NULL,
@@ -4443,7 +4444,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` where <cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` where <cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`))
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
(SELECT 1 FROM t2 WHERE t1.a = t2.a));
@@ -4455,7 +4456,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where exists((select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where exists((/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (/* select#3 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
DROP TABLE t1,t2;
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -4535,13 +4536,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT min(a) FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 0
SET join_cache_level=@save_join_cache_level;
DROP TABLE t1;
#
@@ -4632,7 +4633,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index ca0a33382ff..8500fa2434c 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -33,7 +33,7 @@ NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
Note 1249 Select 4 was reduced during optimization
-Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
+Note 1003 /* select#1 */ select 1 AS `(SELECT 1)` union /* select#3 */ select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
@@ -45,7 +45,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (select 0 union select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
+Note 1003 /* select#1 */ select (/* select#3 */ select 0 union /* select#4 */ select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -63,7 +63,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from dual having (select 1) = 1
+Note 1003 /* select#1 */ select 1 AS `1` from dual having (/* select#3 */ select 1) = 1
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -204,7 +204,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
+Note 1003 (/* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (/* select#3 */ select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (/* select#4 */ select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -222,7 +222,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
+Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
set optimizer_switch=@tmp_optimizer_switch;
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
@@ -244,7 +244,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t4`.`b` AS `b`,(select avg(`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
+Note 1003 /* select#1 */ select `test`.`t4`.`b` AS `b`,(/* select#2 */ select avg(`test`.`t2`.`a` + (/* select#3 */ select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -290,7 +290,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -334,7 +334,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select (select 2 from dual where 2 = `test`.`t2`.`a` union select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
+Note 1003 /* select#1 */ select (/* select#2 */ select 2 from dual where 2 = `test`.`t2`.`a` union /* select#3 */ select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -387,7 +387,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
-Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
+Note 1003 /* select#1 */ select 'joce' AS `pseudo`,(/* select#2 */ select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -419,7 +419,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 100.00 Using where; Using index
Warnings:
-Note 1003 select (select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 /* select#1 */ select (/* select#2 */ select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -440,7 +440,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -572,7 +572,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 3 AS `numreponse` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 3 AS `numreponse` from `test`.`t1` where 1
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -613,11 +613,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b in (select b from t1);
-ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data
+affected rows: 3
+insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
a b
0 10
1 11
@@ -769,7 +770,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3)))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union /* select#3 */ select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3)))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -917,7 +918,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -932,7 +933,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null)) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null) having `test`.`t2`.`a` is null)) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1171,19 +1172,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1266,7 +1267,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) NOT NULL
+ `a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1278,7 +1279,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(select (select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#2 */ select (/* select#3 */ select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1332,7 +1333,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1342,7 +1343,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1387,7 +1388,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`)
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1620,25 +1621,25 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1653,7 +1654,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1661,7 +1662,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1672,7 +1673,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1680,7 +1681,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1688,7 +1689,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1696,7 +1697,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1704,7 +1705,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1712,7 +1713,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1723,7 +1724,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using temporary
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(/* select#2 */ select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1774,7 +1775,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION t1 system NULL NULL NULL NULL 1 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 'e' AS `s1` from dual where 1
+Note 1003 /* select#1 */ select 'e' AS `s1` from dual where 1
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1893,14 +1894,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where `test`.`t1`.`id` < 8 and <cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,exists(select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null))
+Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -2984,7 +2985,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -2997,7 +2998,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' and trigcond(trigcond(<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one` or `test`.`t2`.`one` is null)) and trigcond(trigcond(<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two` or `test`.`t2`.`two` is null)) having trigcond(`test`.`t2`.`one` is null) and trigcond(`test`.`t2`.`two` is null))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -4254,7 +4255,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `res`.`count(*)` AS `count(*)` from (select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
+Note 1003 /* select#1 */ select `res`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
DROP TABLE t1;
CREATE TABLE t1 (
a varchar(255) default NULL,
@@ -4463,7 +4464,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where exists((select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where exists((/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (/* select#3 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`))
DROP TABLE t1,t2;
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -4544,14 +4545,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
+Note 1003 /* select#1 */ select 1 AS `1` from <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT min(a) FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1` where `test`.`t1`.`a` > 3 group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
+Note 1003 /* select#1 */ select 1 AS `1` from <materialize> (/* select#2 */ select min(`test`.`t1`.`a`) from `test`.`t1` where `test`.`t1`.`a` > 3 group by `test`.`t1`.`a`) join `test`.`t1` where `<subquery2>`.`min(a)` = 1
SET join_cache_level=@save_join_cache_level;
DROP TABLE t1;
#
@@ -4642,7 +4643,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index e789deb1b8b..48bf9ce90c9 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -30,7 +30,7 @@ NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
Note 1249 Select 4 was reduced during optimization
-Note 1003 select 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
+Note 1003 /* select#1 */ select 1 AS `(SELECT 1)` union /* select#3 */ select 2 AS `(SELECT 2)`
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
@@ -42,7 +42,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1249 Select 2 was reduced during optimization
-Note 1003 select (select 0 union select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
+Note 1003 /* select#1 */ select (/* select#3 */ select 0 union /* select#4 */ select 0) AS `(SELECT (SELECT 0 UNION SELECT 0))`
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -60,7 +60,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 1 AS `1` from dual having (select 1) = 1
+Note 1003 /* select#1 */ select 1 AS `1` from dual having (/* select#3 */ select 1) = 1
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@@ -201,7 +201,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
+Note 1003 (/* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` order by 1 desc limit 1)) union (/* select#3 */ select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where `test`.`t4`.`b` = (/* select#4 */ select max(`test`.`t2`.`a`) * 4 from `test`.`t2`))
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -219,7 +219,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
+Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t3`.`a` from `test`.`t3` where `test`.`t3`.`a` < 8 order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`a` > 1) `tt`
set optimizer_switch=@tmp_optimizer_switch;
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
@@ -241,7 +241,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((select avg(`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
+Note 1003 /* select#1 */ select `test`.`t4`.`b` AS `b`,<expr_cache><`test`.`t4`.`a`>((/* select#2 */ select avg(`test`.`t2`.`a` + (/* select#3 */ select min(`test`.`t3`.`a`) from `test`.`t3` where `test`.`t3`.`a` >= `test`.`t4`.`a`)) from `test`.`t2`)) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4`
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
@@ -287,7 +287,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2);
a
7
@@ -331,7 +331,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select <expr_cache><`test`.`t2`.`a`>((select 2 from dual where 2 = `test`.`t2`.`a` union select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
+Note 1003 /* select#1 */ select <expr_cache><`test`.`t2`.`a`>((/* select#2 */ select 2 from dual where 2 = `test`.`t2`.`a` union /* select#3 */ select `test`.`t5`.`a` from `test`.`t5` where `test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2`
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
ERROR 21000: Subquery returns more than 1 row
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -349,7 +349,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t7 index PRIMARY PRIMARY 4 NULL 2 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where <expr_cache><`test`.`t6`.`clinic_uq`>(<in_optimizer>(`test`.`t6`.`clinic_uq`,`test`.`t6`.`clinic_uq` in ( <materialize> (select `test`.`t7`.`uq` from `test`.`t7` where 1 ), <primary_index_lookup>(`test`.`t6`.`clinic_uq` in <temporary table> on distinct_key where `test`.`t6`.`clinic_uq` = `<subquery2>`.`uq`))))
+Note 1003 /* select#1 */ select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where <expr_cache><`test`.`t6`.`clinic_uq`>(<in_optimizer>(`test`.`t6`.`clinic_uq`,`test`.`t6`.`clinic_uq` in ( <materialize> (/* select#2 */ select `test`.`t7`.`uq` from `test`.`t7` where 1 ), <primary_index_lookup>(`test`.`t6`.`clinic_uq` in <temporary table> on distinct_key where `test`.`t6`.`clinic_uq` = `<subquery2>`.`uq`))))
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
ERROR 23000: Column 'a' in field list is ambiguous
drop table t1,t2,t3;
@@ -384,7 +384,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
-Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
+Note 1003 /* select#1 */ select 'joce' AS `pseudo`,(/* select#2 */ select 'test' from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
@@ -416,7 +416,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 100.00 Using where; Using index
Warnings:
-Note 1003 select (select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
+Note 1003 /* select#1 */ select (/* select#2 */ select distinct `test`.`t1`.`date` from `test`.`t1` where `test`.`t1`.`date` = DATE'2002-08-03') AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
2002-08-03
@@ -437,7 +437,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -569,7 +569,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 100.00 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 3 AS `numreponse` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 3 AS `numreponse` from `test`.`t1` where 1
drop table t1;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@@ -610,11 +610,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b in (select b from t1);
-ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data
+affected rows: 3
+insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
a b
0 10
1 11
@@ -766,7 +767,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
+Note 1003 /* select#1 */ select `test`.`t2`.`id` AS `id` from `test`.`t2` where <expr_cache><`test`.`t2`.`id`>(<in_optimizer>(`test`.`t2`.`id`,<exists>(/* select#2 */ select 1 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(1) union /* select#3 */ select 3 having <cache>(`test`.`t2`.`id`) = <ref_null_helper>(3))))
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -914,7 +915,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
2 MATERIALIZED t2 index a a 5 NULL 3 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`a`)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`a`)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -929,7 +930,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t2 index a a 5 NULL 3 100.00 Using index
2 MATERIALIZED t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`a` = `test`.`t2`.`a` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1168,19 +1169,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select rand() from `test`.`t1`) AS `(SELECT RAND() FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select encrypt('test') from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1`
EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select (select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
+Note 1003 /* select#1 */ select (/* select#2 */ select benchmark(1,1) from `test`.`t1`) AS `(SELECT BENCHMARK(1,1) FROM t1)` from `test`.`t1`
drop table t1;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1263,7 +1264,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) NOT NULL
+ `a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1275,7 +1276,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,(select (select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#2 */ select (/* select#3 */ select rand() from `test`.`t1` limit 1) from `test`.`t1` limit 1) AS `(select (select rand() from t1 limit 1) from t1 limit 1)` from `test`.`t1`
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1329,7 +1330,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from dual where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
INSERT INTO t1 (pseudo) VALUES ('test1');
SELECT 0 IN (SELECT 1 FROM t1 a);
0 IN (SELECT 1 FROM t1 a)
@@ -1339,7 +1340,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select <in_optimizer>(0,<exists>(select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
+Note 1003 /* select#1 */ select <in_optimizer>(0,<exists>(/* select#2 */ select 1 from `test`.`t1` `a` where 0 = 1)) AS `0 IN (SELECT 1 FROM t1 a)`
drop table t1;
CREATE TABLE `t1` (
`i` int(11) NOT NULL default '0',
@@ -1384,7 +1385,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ref salary salary 5 const 1 100.00 Using where
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (select max(`test`.`t1`.`salary`) from `test`.`t1`)
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id` from `test`.`t1` where `test`.`t1`.`salary` = (/* select#2 */ select max(`test`.`t1`.`salary`) from `test`.`t1`)
drop table t1;
CREATE TABLE t1 (
ID int(10) unsigned NOT NULL auto_increment,
@@ -1446,7 +1447,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
2 MATERIALIZED t1 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`a`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`a`))))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1456,7 +1457,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
2 MATERIALIZED t1 ALL PRIMARY NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` where `test`.`t1`.`b` <> 30 ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`a`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where `test`.`t1`.`b` <> 30 ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`a`))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1467,7 +1468,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using index
2 MATERIALIZED t1 ALL PRIMARY NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`a` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`a`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`a` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where `test`.`t2`.`a` = `<subquery2>`.`a`))))
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1489,7 +1490,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a))))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1499,7 +1500,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1510,7 +1511,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1167 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`a` and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`a` and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
@@ -1526,7 +1527,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL a 5 NULL 4 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 1001 100.00 Using index; Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on a where `test`.`t1`.`b` <> 30 and <cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
drop table t0, t1, t2, t3;
create table t1 (a int, b int);
create table t2 (a int, b int);
@@ -1617,25 +1618,25 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 MATERIALIZED t2 index s1 s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 MATERIALIZED t2 index s1 s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 MATERIALIZED t2 index s1 s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
2 MATERIALIZED t2 index s1 s1 6 NULL 2 50.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` where `test`.`t2`.`s1` < 'a2' ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` where `test`.`t2`.`s1` < 'a2' ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where `test`.`t1`.`s1` = `<subquery2>`.`s1`)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1650,7 +1651,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2);
a
explain extended select * from t3 where a >= some (select b from t2);
@@ -1658,7 +1659,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= all (select b from t2 group by 1);
a
6
@@ -1669,7 +1670,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select max(NULL) from `test`.`t2`) > <cache>(`test`.`t3`.`a`)))
select * from t3 where a >= some (select b from t2 group by 1);
a
explain extended select * from t3 where a >= some (select b from t2 group by 1);
@@ -1677,7 +1678,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <nop>(<in_optimizer>(`test`.`t3`.`a`,(/* select#2 */ select min(NULL) from `test`.`t2`) <= <cache>(`test`.`t3`.`a`)))
select * from t3 where NULL >= any (select b from t2);
a
explain extended select * from t3 where NULL >= any (select b from t2);
@@ -1685,7 +1686,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= any (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= any (select b from t2 group by 1);
@@ -1693,7 +1694,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2);
a
explain extended select * from t3 where NULL >= some (select b from t2);
@@ -1701,7 +1702,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
select * from t3 where NULL >= some (select b from t2 group by 1);
a
explain extended select * from t3 where NULL >= some (select b from t2 group by 1);
@@ -1709,7 +1710,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where 0
insert into t2 values (2,2), (2,1), (3,3), (3,1);
select * from t3 where a > all (select max(b) from t2 group by a);
a
@@ -1720,7 +1721,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using temporary
Warnings:
-Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a` from `test`.`t3` where <not>(<in_optimizer>(`test`.`t3`.`a`,<max>(/* select#2 */ select max(`test`.`t2`.`b`) from `test`.`t2` group by `test`.`t2`.`a`) >= <cache>(`test`.`t3`.`a`)))
drop table t2, t3;
CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now());
@@ -1771,7 +1772,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 UNION t1 system NULL NULL NULL NULL 1 100.00
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select 'e' AS `s1` from dual where 1
+Note 1003 /* select#1 */ select 'e' AS `s1` from dual where 1
drop table t1;
CREATE TABLE t1 (number char(11) NOT NULL default '') ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('69294728265'),('18621828126'),('89356874041'),('95895001874');
@@ -1890,14 +1891,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
2 MATERIALIZED t1 range PRIMARY PRIMARY 4 NULL 7 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,`test`.`t1`.`id` in ( <materialize> (select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 ), <primary_index_lookup>(`test`.`t1`.`id` in <temporary table> on distinct_key where `test`.`t1`.`id` = `<subquery2>`.`id`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where !<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,`test`.`t1`.`id` in ( <materialize> (/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 ), <primary_index_lookup>(`test`.`t1`.`id` in <temporary table> on distinct_key where `test`.`t1`.`id` = `<subquery2>`.`id`))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null)))
+Note 1003 /* select#1 */ select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where !<in_optimizer>(1,<expr_cache><`test`.`tt`.`id`>(exists(/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where `test`.`t1`.`id` < 8 and `test`.`t1`.`id` = `test`.`tt`.`id` having `test`.`t1`.`id` is not null)))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
@@ -2433,7 +2434,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1276 Field or reference 'test.up.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where <expr_cache><`test`.`up`.`a`>(<in_optimizer>(`test`.`up`.`a`,`test`.`up`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` where 1 ), <primary_index_lookup>(`test`.`up`.`a` in <temporary table> on distinct_key where `test`.`up`.`a` = `<subquery2>`.`a`))))
+Note 1003 /* select#1 */ select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where <expr_cache><`test`.`up`.`a`>(<in_optimizer>(`test`.`up`.`a`,`test`.`up`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` where 1 ), <primary_index_lookup>(`test`.`up`.`a` in <temporary table> on distinct_key where `test`.`up`.`a` = `<subquery2>`.`a`))))
drop table t1;
CREATE TABLE t1 (t1_a int);
INSERT INTO t1 VALUES (1);
@@ -2980,19 +2981,19 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where `test`.`t1`.`one` = `<subquery2>`.`one` and `test`.`t1`.`two` = `<subquery2>`.`two`)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where `test`.`t1`.`one` = `<subquery2>`.`one` and `test`.`t1`.`two` = `<subquery2>`.`two`)))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = 'N' ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where `test`.`t1`.`one` = `<subquery2>`.`one` and `test`.`t1`.`two` = `<subquery2>`.`two`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = 'N' ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where `test`.`t1`.`one` = `<subquery2>`.`one` and `test`.`t1`.`two` = `<subquery2>`.`two`))))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where `test`.`t1`.`one` = `<subquery2>`.`one` and `test`.`t1`.`two` = `<subquery2>`.`two`)))) AS `test` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where `test`.`t2`.`flag` = '0' ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where `test`.`t1`.`one` = `<subquery2>`.`one` and `test`.`t1`.`two` = `<subquery2>`.`two`)))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -4247,7 +4248,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
Warnings:
-Note 1003 select `res`.`count(*)` AS `count(*)` from (select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
+Note 1003 /* select#1 */ select `res`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` group by `test`.`t1`.`a`) `res`
DROP TABLE t1;
CREATE TABLE t1 (
a varchar(255) default NULL,
@@ -4443,7 +4444,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`a` from `test`.`t2` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`a`))))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` where 1 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`a`))))
EXPLAIN EXTENDED
SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
(SELECT 1 FROM t2 WHERE t1.a = t2.a));
@@ -4455,7 +4456,7 @@ NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1
-Note 1003 select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
+Note 1003 /* select#1 */ select 2 AS `2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a`>(exists((/* select#2 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) union (/* select#3 */ select 1 from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)))
DROP TABLE t1,t2;
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -4535,13 +4536,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT min(a) FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 0
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 0
SET join_cache_level=@save_join_cache_level;
DROP TABLE t1;
#
@@ -4632,7 +4633,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where 1
+Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` where 1
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
diff --git a/mysql-test/r/subselect_partial_match.result b/mysql-test/r/subselect_partial_match.result
index 256295cef28..5f444457794 100644
--- a/mysql-test/r/subselect_partial_match.result
+++ b/mysql-test/r/subselect_partial_match.result
@@ -775,7 +775,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using where
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00
Warnings:
-Note 1003 select `table1`.`a1` AS `a1`,`table1`.`a2` AS `a2` from (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b2` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery3>`.`b2`)))) `table1`
+Note 1003 /* select#1 */ select `table1`.`a1` AS `a1`,`table1`.`a2` AS `a2` from (/* select#2 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where !<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (/* select#3 */ select `test`.`t2`.`b2` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery3>`.`b2`)))) `table1`
set optimizer_switch=@tmp_optimizer_switch;
DROP TABLE t1, t2;
#
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index c39593e5213..a601dac5337 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -84,7 +84,7 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on(`test`.`A`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`B`.`A`,`test`.`B`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`B`.`A` in <temporAry tABle> on distinct_key where `test`.`B`.`A` = `<suBquery2>`.`pk`)))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on(`test`.`A`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`B`.`A`,`test`.`B`.`A` in ( <mAteriAlize> (/* select#2 */ select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`B`.`A` in <temporAry tABle> on distinct_key where `test`.`B`.`A` = `<suBquery2>`.`pk`)))) where 1
t2 should be wrapped into OJ-nest, so we have "t1 LJ (t2 J t10)"
explAin extended
select * from t1 left join t2 on (t2.A= t1.A And t2.A in (select pk from t10));
@@ -93,7 +93,7 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
2 MATERIALIZED t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`t1`.`A`,`test`.`t1`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t1`.`A` in <temporAry tABle> on distinct_key where `test`.`t1`.`A` = `<suBquery2>`.`pk`)))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`t1`.`A`,`test`.`t1`.`A` in ( <mAteriAlize> (/* select#2 */ select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t1`.`A` in <temporAry tABle> on distinct_key where `test`.`t1`.`A` = `<suBquery2>`.`pk`)))) where 1
set join_buffer_size=8*1024;
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
@@ -767,11 +767,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
show warnings;
Level Code Message
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
select a from t1
where a in (select c from t2 where d >= some(select e from t3 where b=e));
a
@@ -3142,7 +3142,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(`test`.`t3`.`c3` = `test`.`t1`.`c1` and <cache>(<in_optimizer>(1,<exists>(select `test`.`t4`.`c4` from `test`.`t4` where 1 = `test`.`t4`.`c4`)))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(`test`.`t3`.`c3` = `test`.`t1`.`c1` and <cache>(<in_optimizer>(1,<exists>(/* select#2 */ select `test`.`t4`.`c4` from `test`.`t4` where 1 = `test`.`t4`.`c4`)))) where 1
# mdev-12820
SELECT *
FROM t1
@@ -3163,6 +3163,6 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 100.00
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(`test`.`t2`.`c2` = `test`.`t1`.`c1` and <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t3`.`c3` from `test`.`t3` where <cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(`test`.`t2`.`c2` = `test`.`t1`.`c1` and <in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#3 */ select `test`.`t3`.`c3` from `test`.`t3` where <cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))) where 1
DROP TABLE t1,t2,t3,t4;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index 3ff0e619188..6a1f310511f 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -1588,7 +1588,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
2 DEPENDENT SUBQUERY t3 hash_ALL NULL #hash#$hj 5 func 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` where <expr_cache><`test`.`t1`.`i1`>(<in_optimizer>(`test`.`t1`.`i1`,<exists>(select `test`.`t3`.`i3` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`i3` = `test`.`t2`.`i2` and <cache>(`test`.`t1`.`i1`) = `test`.`t3`.`i3`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`i1` AS `i1` from `test`.`t1` where <expr_cache><`test`.`t1`.`i1`>(<in_optimizer>(`test`.`t1`.`i1`,<exists>(/* select#2 */ select `test`.`t3`.`i3` from `test`.`t2` join `test`.`t3` where `test`.`t3`.`i3` = `test`.`t2`.`i2` and <cache>(`test`.`t1`.`i1`) = `test`.`t3`.`i3`)))
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
i1
7
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 9d5ee4ba263..77a073ea2d3 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -97,7 +97,7 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer (incrementAl, BNL join)
2 MATERIALIZED t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on(`test`.`A`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`B`.`A`,`test`.`B`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`B`.`A` in <temporAry tABle> on distinct_key where `test`.`B`.`A` = `<suBquery2>`.`pk`)))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on(`test`.`A`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`B`.`A`,`test`.`B`.`A` in ( <mAteriAlize> (/* select#2 */ select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`B`.`A` in <temporAry tABle> on distinct_key where `test`.`B`.`A` = `<suBquery2>`.`pk`)))) where 1
t2 should be wrapped into OJ-nest, so we have "t1 LJ (t2 J t10)"
explAin extended
select * from t1 left join t2 on (t2.A= t1.A And t2.A in (select pk from t10));
@@ -106,7 +106,7 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer (flAt, BNL join)
2 MATERIALIZED t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`t1`.`A`,`test`.`t1`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t1`.`A` in <temporAry tABle> on distinct_key where `test`.`t1`.`A` = `<suBquery2>`.`pk`)))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`A` = `test`.`t1`.`A` And <in_optimizer>(`test`.`t1`.`A`,`test`.`t1`.`A` in ( <mAteriAlize> (/* select#2 */ select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t1`.`A` in <temporAry tABle> on distinct_key where `test`.`t1`.`A` = `<suBquery2>`.`pk`)))) where 1
set join_buffer_size=8*1024;
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
@@ -780,11 +780,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
show warnings;
Level Code Message
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`c` = `test`.`t1`.`a` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
select a from t1
where a in (select c from t2 where d >= some(select e from t3 where b=e));
a
@@ -3156,7 +3156,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (incremental, BNL join)
2 SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(`test`.`t3`.`c3` = `test`.`t1`.`c1` and <cache>(<in_optimizer>(1,<exists>(select `test`.`t4`.`c4` from `test`.`t4` where 1 = `test`.`t4`.`c4`)))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(`test`.`t3`.`c3` = `test`.`t1`.`c1` and <cache>(<in_optimizer>(1,<exists>(/* select#2 */ select `test`.`t4`.`c4` from `test`.`t4` where 1 = `test`.`t4`.`c4`)))) where 1
# mdev-12820
SELECT *
FROM t1
@@ -3177,7 +3177,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t4 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (incremental, BNL join)
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(`test`.`t2`.`c2` = `test`.`t1`.`c1` and <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t3`.`c3` from `test`.`t3` where <cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))) where 1
+Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(`test`.`t2`.`c2` = `test`.`t1`.`c1` and <in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#3 */ select `test`.`t3`.`c3` from `test`.`t3` where <cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))) where 1
DROP TABLE t1,t2,t3,t4;
set optimizer_switch=@subselect_sj_tmp;
#
diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result
index 8109c36441e..9e1870875ce 100644
--- a/mysql-test/r/subselect_sj_mat.result
+++ b/mysql-test/r/subselect_sj_mat.result
@@ -86,7 +86,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 test.t1.a1,test.t1.a2 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1`,min(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`b1` > '0' group by `test`.`t2`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2`.`b1`,min(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`b1` > '0' group by `test`.`t2`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1`.`a2`
select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -109,7 +109,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key # 8 # 1 100.00 #
2 MATERIALIZED t2i range it2i1,it2i3 # 9 # 5 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select max(`test`.`t2i`.`b1`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1i` where `<subquery2>`.`max(b1)` = `test`.`t1i`.`a1`
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (/* select#2 */ select max(`test`.`t2i`.`b1`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1i` where `<subquery2>`.`max(b1)` = `test`.`t1i`.`a1`
select * from t1i where a1 in (select max(b1) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -132,7 +132,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key # # # 1 100.00 #
2 MATERIALIZED t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1i` where `<subquery2>`.`b1` = `test`.`t1i`.`a1` and `<subquery2>`.`max(b2)` = `test`.`t1i`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1i` where `<subquery2>`.`b1` = `test`.`t1i`.`a1` and `<subquery2>`.`max(b2)` = `test`.`t1i`.`a2`
select * from t1i where (a1, a2) in (select b1, max(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -144,7 +144,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key # # # 1 100.00 #
2 MATERIALIZED t2i range it2i1,it2i3 # # # 3 100.00 #
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1i` where `<subquery2>`.`b1` = `test`.`t1i`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1i`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1i` where `<subquery2>`.`b1` = `test`.`t1i`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1i`.`a2`
select * from t1i where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -156,7 +156,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 test.t1.a1,test.t1.a2 1 100.00
2 MATERIALIZED t2i range NULL it2i3 9 NULL 3 100.00 Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` group by `test`.`t2i`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`max(b2)` = `test`.`t1`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,max(`test`.`t2i`.`b2`) from `test`.`t2i` group by `test`.`t2i`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`max(b2)` = `test`.`t1`.`a2`
select * from t1 where (a1, a2) in (select b1, max(b2) from t2i group by b1);
a1 a2
1 - 01 2 - 01
@@ -188,7 +188,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 test.t1.a1,test.t1.a2 1 100.00
2 MATERIALIZED t2i range it2i1,it2i3 it2i3 18 NULL 3 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,min(`test`.`t2i`.`b2`) from `test`.`t2i` where `test`.`t2i`.`b1` > '0' group by `test`.`t2i`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1`.`a2`
select * from t1 where (a1, a2) in (select b1, min(b2) from t2i where b1 > '0' group by b1);
a1 a2
1 - 01 2 - 01
@@ -236,7 +236,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 test.t1.a1,test.t1.a2 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`b2` = `test`.`t1`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` order by `test`.`t2`.`b1`,`test`.`t2`.`b2`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`b2` = `test`.`t1`.`a2`
select * from t1 where (a1, a2) in (select b1, b2 from t2 order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -248,7 +248,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 test.t1i.a1,test.t1i.a2 1 100.00
2 MATERIALIZED t2i index NULL it2i3 18 NULL 5 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where `<subquery2>`.`b1` = `test`.`t1i`.`a1` and `<subquery2>`.`b2` = `test`.`t1i`.`a2`
+Note 1003 /* select#1 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` order by `test`.`t2i`.`b1`,`test`.`t2i`.`b2`) join `test`.`t1i` where `<subquery2>`.`b1` = `test`.`t1i`.`a1` and `<subquery2>`.`b2` = `test`.`t1i`.`a2`
select * from t1i where (a1, a2) in (select b1, b2 from t2i order by b1, b2);
a1 a2
1 - 01 2 - 01
@@ -349,7 +349,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and (<expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and `test`.`t3`.`c2` > '0'
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and (<expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#3 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and `test`.`t3`.`c2` > '0'
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -375,7 +375,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where `test`.`t2i`.`b1` = `test`.`t3c`.`c1` and `test`.`t2`.`b1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t3c`.`c2` and `test`.`t2`.`b2` = `test`.`t1`.`a2` and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and `test`.`t3c`.`c2` > '0'
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where `test`.`t2i`.`b1` = `test`.`t3c`.`c1` and `test`.`t2`.`b1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t3c`.`c2` and `test`.`t2`.`b2` = `test`.`t1`.`a2` and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(/* select#3 */ select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and `test`.`t3c`.`c2` > '0'
select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 t3a where c1 = a1) or
@@ -413,7 +413,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
7 UNION t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 #
NULL UNION RESULT <union1,7> ALL NULL # # # NULL NULL #
Warnings:
-Note 1003 (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and (<expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and `test`.`t3`.`c2` > '0') union (select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) semi join (`test`.`t2i` join `test`.`t3i`) where `test`.`t1i`.`a1` = `test`.`t2i`.`b1` and `test`.`t3i`.`c1` = `test`.`t2i`.`b1` and `test`.`t2i`.`b1` = `test`.`t2i`.`b1` and `test`.`t1i`.`a2` = `test`.`t2i`.`b2` and `test`.`t3i`.`c2` = `test`.`t2i`.`b2` and `test`.`t2i`.`b2` = `test`.`t2i`.`b2` and `test`.`t2i`.`b1` > '0' and `test`.`t2i`.`b2` > '0')
+Note 1003 (/* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and (<expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#3 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%02' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery3>`.`c2`)))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3`.`c2` from `test`.`t3` where `test`.`t3`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`))))) and `test`.`t3`.`c2` > '0') union (/* select#7 */ select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) semi join (`test`.`t2i` join `test`.`t3i`) where `test`.`t1i`.`a1` = `test`.`t2i`.`b1` and `test`.`t3i`.`c1` = `test`.`t2i`.`b1` and `test`.`t2i`.`b1` = `test`.`t2i`.`b1` and `test`.`t1i`.`a2` = `test`.`t2i`.`b2` and `test`.`t3i`.`c2` = `test`.`t2i`.`b2` and `test`.`t2i`.`b2` = `test`.`t2i`.`b2` and `test`.`t2i`.`b1` > '0' and `test`.`t2i`.`b2` > '0')
(select * from t1
where (a1, a2) in (select b1, b2 from t2
where b2 in (select c2 from t3 where c2 LIKE '%02') or
@@ -443,7 +443,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
select * from t1
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(a1, a2) in (select c1, c2 from t3
@@ -467,7 +467,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -489,7 +489,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`>(<in_optimizer>(`test`.`t3`.`c1`,<exists>(select `test`.`t1`.`a1` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t3`.`c1`) = `test`.`t1`.`a1` union select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t3`.`c1`) = `test`.`t2`.`b1`)))
+Note 1003 /* select#1 */ select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`>(<in_optimizer>(`test`.`t3`.`c1`,<exists>(/* select#2 */ select `test`.`t1`.`a1` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t3`.`c1`) = `test`.`t1`.`a1` union /* select#3 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t3`.`c1`) = `test`.`t2`.`b1`)))
select * from t3
where c1 in (select a1 from t1 where a1 > '0' UNION select b1 from t2 where b1 < '9');
c1 c2
@@ -513,14 +513,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where `test`.`t2i`.`b1` = `test`.`t1`.`a1` and `test`.`t3c`.`c1` = `test`.`t1`.`a1` and `test`.`t2`.`b1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t1`.`a2` and `test`.`t3c`.`c2` = `test`.`t1`.`a2` and `test`.`t2`.`b2` = `test`.`t1`.`a2` and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`)))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where `test`.`t2i`.`b1` = `test`.`t1`.`a1` and `test`.`t3c`.`c1` = `test`.`t1`.`a1` and `test`.`t2`.`b1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t1`.`a2` and `test`.`t3c`.`c2` = `test`.`t1`.`a2` and `test`.`t2`.`b2` = `test`.`t1`.`a2` and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(/* select#3 */ select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where `test`.`t3a`.`c1` = `test`.`t1`.`a1` and <cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (/* select#4 */ select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where `test`.`t3b`.`c2` like '%03' ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where `test`.`t2`.`b2` = `<subquery4>`.`c2`)))))
explain extended
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01');
a1 a2
1 - 01 2 - 01
@@ -530,7 +530,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select '1 - 01','2 - 01' having (<cache>(`test`.`t1`.`a1`) = '1 - 01' or '1 - 01' is null) and (<cache>(`test`.`t1`.`a2`) = '2 - 01' or '2 - 01' is null) and '1 - 01' is null and '2 - 01' is null)))
select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01' from dual);
a1 a2
1 - 01 2 - 01
@@ -552,7 +552,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
2 SUBQUERY columns index NULL PRIMARY 4 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by (select `test`.`columns`.`col` from `test`.`columns` limit 1)
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by (/* select#2 */ select `test`.`columns`.`col` from `test`.`columns` limit 1)
select * from t1 group by (select col from columns limit 1);
a1 a2
1 - 00 2 - 00
@@ -562,7 +562,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using temporary; Using filesort
2 DEPENDENT SUBQUERY columns unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where; Full scan on NULL key
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`a1`) in columns on PRIMARY where trigcond(<cache>(`test`.`t1`.`a1`) = `test`.`columns`.`col`)))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` group by <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`a1`) in columns on PRIMARY where trigcond(<cache>(`test`.`t1`.`a1`) = `test`.`columns`.`col`)))))
select * from t1 group by (a1 in (select col from columns));
a1 a2
1 - 00 2 - 00
@@ -577,7 +577,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
2 SUBQUERY columns index NULL PRIMARY 4 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` order by (select `test`.`columns`.`col` from `test`.`columns` limit 1)
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` order by (/* select#2 */ select `test`.`columns`.`col` from `test`.`columns` limit 1)
select * from t1 order by (select col from columns limit 1);
a1 a2
1 - 00 2 - 00
@@ -666,7 +666,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where
2 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,<exists>(select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2` having <cache>(`test`.`t1_16`.`a1`) = <ref_null_helper>(group_concat(`test`.`t2_16`.`b1` separator ',')))))
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`>(<in_optimizer>(`test`.`t1_16`.`a1`,<exists>(/* select#2 */ select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2` having <cache>(`test`.`t1_16`.`a1`) = <ref_null_helper>(group_concat(`test`.`t2_16`.`b1` separator ',')))))
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -682,7 +682,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_16.a1 1 100.00 Using where
2 MATERIALIZED t2_16 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2`) join `test`.`t1_16` where `test`.`t1_16`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_16`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_16`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_16`.`b1` separator ',') from `test`.`t2_16` group by `test`.`t2_16`.`b2`) join `test`.`t1_16` where `test`.`t1_16`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_16
where a1 in (select group_concat(b1) from t2_16 group by b2);
@@ -782,7 +782,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_512.a1 1 100.00 Using where
2 MATERIALIZED t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -800,7 +800,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_512.a1 1 100.00 Using where
2 MATERIALIZED t2_512 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_512`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_512`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_512`.`b1` separator ',') from `test`.`t2_512` group by `test`.`t2_512`.`b2`) join `test`.`t1_512` where `test`.`t1_512`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_512
where a1 in (select group_concat(b1) from t2_512 group by b2);
@@ -885,7 +885,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_1024.a1 1 100.00 Using where
2 MATERIALIZED t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -903,7 +903,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_1024.a1 1 100.00 Using where
2 MATERIALIZED t2_1024 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_1024`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1024`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_1024`.`b1` separator ',') from `test`.`t2_1024` group by `test`.`t2_1024`.`b2`) join `test`.`t1_1024` where `test`.`t1_1024`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_1024
where a1 in (select group_concat(b1) from t2_1024 group by b2);
@@ -988,7 +988,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_1025.a1 1 100.00 Using where
2 MATERIALIZED t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -1006,7 +1006,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 260 test.t1_1025.a1 1 100.00 Using where
2 MATERIALIZED t2_1025 ALL NULL NULL NULL NULL 3 100.00 Using filesort
Warnings:
-Note 1003 select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`
+Note 1003 /* select#1 */ select left(`test`.`t1_1025`.`a1`,7) AS `left(a1,7)`,left(`test`.`t1_1025`.`a2`,7) AS `left(a2,7)` from <materialize> (/* select#2 */ select group_concat(`test`.`t2_1025`.`b1` separator ',') from `test`.`t2_1025` group by `test`.`t2_1025`.`b2`) join `test`.`t1_1025` where `test`.`t1_1025`.`a1` = `<subquery2>`.`group_concat(b1)`
select left(a1,7), left(a2,7)
from t1_1025
where a1 in (select group_concat(b1) from t2_1025 group by b2);
@@ -1147,7 +1147,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1159,7 +1159,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL it1a 4 NULL 7 100.00 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where `test`.`t2`.`d` >= 20 ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where `test`.`t1`.`a` = `<subquery2>`.`c`))))
select a from t1 group by a having a in (select c from t2 where d >= 20);
a
2
@@ -1174,7 +1174,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
Note 1981 Aggregate function 'max()' of SELECT #3 belongs to SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`c` from `test`.`t2` where <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where max(`test`.`t1`.`b`) = `test`.`t3`.`e` having <cache>(`test`.`t2`.`d`) >= <ref_null_helper>(`test`.`t3`.`e`))))) and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`c`)))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` having <expr_cache><`test`.`t1`.`a`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select `test`.`t2`.`c` from `test`.`t2` where <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`,max(`test`.`t1`.`b`),max(`test`.`t1`.`b`)>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where max(`test`.`t1`.`b`) = `test`.`t3`.`e` having <cache>(`test`.`t2`.`d`) >= <ref_null_helper>(`test`.`t3`.`e`))))) and <cache>(`test`.`t1`.`a`) = `test`.`t2`.`c`)))
select a from t1 group by a
having a in (select c from t2 where d >= some(select e from t3 where max(b)=e));
a
@@ -1189,7 +1189,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t1`.`a` = `test`.`t2`.`c` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t1`.`a` = `test`.`t2`.`c` and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(/* select#3 */ select `test`.`t3`.`e` from `test`.`t3` where `test`.`t1`.`b` = `test`.`t3`.`e` and <cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))
select a from t1
where a in (select c from t2 where d >= some(select e from t3 where b=e));
a
@@ -1862,7 +1862,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <subquery2> system NULL NULL NULL NULL 1 100.00
2 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
-Note 1003 select 8 AS `a` from dual where 1
+Note 1003 /* select#1 */ select 8 AS `a` from dual where 1
DROP TABLE t1;
#
# BUG#904432: Wrong result with LEFT JOIN, constant table, semijoin=ON,materialization=ON
@@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
SELECT * FROM t1
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
a b
@@ -2291,7 +2291,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t3 ALL NULL NULL NULL NULL 8 100.00
Warnings:
Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`f1` = `test`.`t3`.`f3`))
+Note 1003 /* select#1 */ select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`>(exists(/* select#2 */ select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`f1` = `test`.`t3`.`f3`))
# this checks the result set above
set optimizer_switch= 'materialization=off,semijoin=off';
SELECT * FROM t1
@@ -2329,7 +2329,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00
Warnings:
Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`f1` AS `f1`,<expr_cache><`test`.`t1`.`pk`>((select count(0) from `test`.`t2` semi join (`test`.`t2`) where `test`.`t1`.`pk` = `test`.`t2`.`f2`)) AS `sq` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`f1` AS `f1`,<expr_cache><`test`.`t1`.`pk`>((/* select#2 */ select count(0) from `test`.`t2` semi join (`test`.`t2`) where `test`.`t1`.`pk` = `test`.`t2`.`f2`)) AS `sq` from `test`.`t1`
# this checks the result set above
set @save_optimizer_switch= @@optimizer_switch;
set optimizer_switch= 'materialization=off,semijoin=off';
diff --git a/mysql-test/r/table_elim.result b/mysql-test/r/table_elim.result
index 764a1b2780e..04a9b47b6c9 100644
--- a/mysql-test/r/table_elim.result
+++ b/mysql-test/r/table_elim.result
@@ -126,7 +126,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY f range PRIMARY PRIMARY 4 NULL 4 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` where `f`.`id` in (1,2,3,4)
+Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` where `f`.`id` in (1,2,3,4)
This should use facts and a1 tables:
explain extended select id from v1 where attr1 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -134,7 +134,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` where `f`.`id` = `a1`.`id` and `a1`.`attr1` between 12 and 14
+Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` where `f`.`id` = `a1`.`id` and `a1`.`attr1` between 12 and 14
This should use facts, a2 and its subquery:
explain extended select id from v1 where attr2 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -143,7 +143,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.a2.id 2 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = (select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `a2`.`id`)
+Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = (/* select#3 */ select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `a2`.`id`)
This should use one table:
explain select id from v2 where id=2;
id select_type table type possible_keys key key_len ref rows Extra
@@ -154,7 +154,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY f range PRIMARY PRIMARY 4 NULL 4 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` where `f`.`id` in (1,2,3,4)
+Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` where `f`.`id` in (1,2,3,4)
This should use facts and a1 tables:
explain extended select id from v2 where attr1 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -162,7 +162,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` where `f`.`id` = `a1`.`id` and `a1`.`attr1` between 12 and 14
+Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` where `f`.`id` = `a1`.`id` and `a1`.`attr1` between 12 and 14
This should use facts, a2 and its subquery:
explain extended select id from v2 where attr2 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
@@ -171,7 +171,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.f.id 2 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = (select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `f`.`id`)
+Note 1003 /* select#1 */ select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where `f`.`id` = `a2`.`id` and `a2`.`attr2` between 12 and 14 and `a2`.`fromdate` = (/* select#3 */ select max(`test`.`t2`.`fromdate`) from `test`.`t2` where `test`.`t2`.`id` = `f`.`id`)
drop view v1, v2;
drop table t0, t1, t2;
create table t1 (a int);
@@ -655,7 +655,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL b 5 NULL 2 100.00 Using where; Using index
2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t2`.`b` AS `b` from `test`.`t2` where <expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(select sum(1) from dual where 1 having <cache>(`test`.`t2`.`b`) = <ref_null_helper>(sum(1)))))
+Note 1003 /* select#1 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` where <expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(/* select#2 */ select sum(1) from dual where 1 having <cache>(`test`.`t2`.`b`) = <ref_null_helper>(sum(1)))))
DROP TABLE t1,t2;
#
# MDEV-4840: Wrong result (missing rows) on LEFT JOIN with InnoDB tables
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index b833f4f9768..d1bec4a2af5 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -181,20 +181,20 @@ CREATE TABLE t2 ( c FLOAT(30,18) );
INSERT INTO t2 VALUES( 123456 );
SELECT AVG( c ) FROM t1 UNION SELECT 1;
AVG( c )
-12139
-1
+12139.000000000000000000
+1.000000000000000000
SELECT 1 UNION SELECT AVG( c ) FROM t1;
1
-1
-12139
+1.000000000000000000
+12139.000000000000000000
SELECT 1 UNION SELECT * FROM t2 UNION SELECT 1;
1
-1
-123456
+1.000000000000000000
+123456.000000000000000000
SELECT c/1 FROM t1 UNION SELECT 1;
c/1
-12139
-1
+12139.000000000000000000
+1.000000000000000000
DROP TABLE t1, t2;
create temporary table t1 (a int);
insert into t1 values (4711);
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 24a914663b7..b751632307a 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -301,11 +301,11 @@ create trigger trg before insert on t2 for each row set @a:=1;
ERROR 42S02: Table 'test.t2' doesn't exist
create trigger trg before insert on t1 for each row set @a:=1;
create trigger trg after insert on t1 for each row set @a:=1;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg' already exists
create trigger trg2 before insert on t1 for each row set @a:=1;
drop trigger trg2;
create trigger trg before insert on t3 for each row set @a:=1;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg' already exists
create trigger trg2 before insert on t3 for each row set @a:=1;
drop trigger trg2;
drop trigger trg;
@@ -313,7 +313,7 @@ drop trigger trg;
ERROR HY000: Trigger does not exist
create view v1 as select * from t1;
create trigger trg before insert on v1 for each row set @a:=1;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
drop view v1;
drop table t1;
drop table t3;
@@ -1986,7 +1986,7 @@ drop table if exists t1;
create table t1 (i int, j int);
create trigger t1_bi before insert on t1 for each row begin end;
create trigger t1_bi before insert on t1 for each row begin end;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.t1_bi' already exists
create trigger t1_bi2 before insert on t1 for each row begin end;
drop trigger t1_bi;
drop trigger t1_bi2;
@@ -2368,7 +2368,6 @@ tr1 1 2016-01-01 10:10:10.33
tr2 2 2016-01-01 10:10:10.99
drop table t1;
set time_zone= @@global.time_zone;
-#
# MDEV-12992: Increasing memory consumption
with each invocation of trigger
#
@@ -2379,3 +2378,23 @@ CREATE TRIGGER tr
AFTER UPDATE ON t1 FOR EACH ROW SELECT (SELECT b FROM t2) INTO @x;
# Running 20000 queries
DROP TABLE t1,t2;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+#
+CREATE TABLE t1 (a INT, b INT, total INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+DECLARE va TYPE OF t1.a DEFAULT NEW.a;
+DECLARE vb TYPE OF t1.b DEFAULT NEW.b;
+SET NEW.total:= va + vb;
+END;
+$$
+INSERT INTO t1 (a,b) VALUES (10, 20);
+SELECT * FROM t1;
+a b total
+10 20 30
+DROP TABLE t1;
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 4b0e4a61c64..d56fac962fe 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -429,17 +429,26 @@ select @a;
#
# BUG LP:1008487 virtual bool Item_cache::is_expensive(): Assertion `example' failed
#
+SET TIMESTAMP=UNIX_TIMESTAMP('2017-01-03 00:00:00');
create table t1(a date,key(a));
insert into t1 values ('2012-01-01'),('2012-02-02');
explain
select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1_0 ref a a 4 const 0 Using where; Using index
+1 SIMPLE t1_0 ref a a 4 const 1 Using where; Using index
1 SIMPLE t2 index NULL a 4 NULL 2 Using index; Using join buffer (flat, BNL join)
1 SIMPLE t1 index NULL a 4 NULL 2 Using index; Using join buffer (incremental, BNL join)
select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
1
+SET TIMESTAMP=UNIX_TIMESTAMP('2012-01-03 00:00:01');
+explain
+select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
+1
drop table t1;
+SET TIMESTAMP=DEFAULT;
#
# MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null
# MDEV-9972 Least function retuns date in date time format
@@ -606,14 +615,14 @@ SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' 2001-01-01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-01' and <cache>(length(DATE'2001-01-01')) = 11 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-01' and <cache>(octet_length(DATE'2001-01-01')) = 11 + rand()
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' garbage ';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Warning 1292 Incorrect datetime value: ' garbage '
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'0000-00-00' and <cache>(length(DATE'0000-00-00')) = 11 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'0000-00-00' and <cache>(octet_length(DATE'0000-00-00')) = 11 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-01');
@@ -632,7 +641,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=8+RAND() AND a='20010101';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-01' and <cache>(length(DATE'2001-01-01')) = 8 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-01' and <cache>(octet_length(DATE'2001-01-01')) = 8 + rand()
DROP TABLE t1;
#
# MDEV-8706 Wrong result for SELECT..WHERE time_column=TIMESTAMP'2015-08-30 00:00:00' AND time_column='00:00:00'
@@ -661,7 +670,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2015-08-30' and <cache>(length(DATE'2015-08-30')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2015-08-30' and <cache>(octet_length(DATE'2015-08-30')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2015-08-30'),('2015-08-31');
@@ -686,7 +695,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'24:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2015-08-31' and <cache>(length(DATE'2015-08-31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2015-08-31' and <cache>(octet_length(DATE'2015-08-31')) = 30 + rand()
DROP TABLE t1;
# In this example '00:00:00' is not recognized as TIME'00:00:00'
# and is treated as DATE'0000-00-00'.
@@ -712,7 +721,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'0000-00-00' and <cache>(length(DATE'0000-00-00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'0000-00-00' and <cache>(octet_length(DATE'0000-00-00')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2015-08-30'),('2015-08-31');
@@ -737,7 +746,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2015-08-30 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2015-08-30 00:00:00' and <cache>(length(DATE'2015-08-30')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2015-08-30 00:00:00' and <cache>(octet_length(DATE'2015-08-30')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2015-08-30'),('2015-08-31');
@@ -760,7 +769,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2015-08-30 00:00:00.1
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2015-08-30 00:00:00.1' and <cache>(length(DATE'2015-08-30')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2015-08-30 00:00:00.1' and <cache>(octet_length(DATE'2015-08-30')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2015-08-30'),('2015-08-31');
@@ -785,7 +794,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='2015-08-30 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2015-08-30' and <cache>(length(DATE'2015-08-30')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2015-08-30' and <cache>(octet_length(DATE'2015-08-30')) = 30 + rand()
DROP TABLE t1;
SET timestamp=DEFAULT;
#
@@ -845,3 +854,27 @@ DROP TABLE t1;
#
# End of 10.1 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12721 Wrong execution plan for WHERE (date_field <=> timestamp_expr AND TRUE)
+#
+CREATE TABLE t1(a DATE,KEY(a));
+INSERT INTO t1 VALUES ('2012-01-01'),('2012-02-02');
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP'2001-01-01 00:00:01' AND TRUE;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP('2001-01-01', '00:00:01') AND TRUE;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP'2001-01-01 00:00:00' AND TRUE;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 4 const 1 Using where; Using index
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP('2001-01-01', '00:00:00') AND TRUE;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 4 const 1 Using where; Using index
+DROP TABLE t1;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index c9b3358cca4..95e421821c1 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -984,7 +984,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) <> 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -1006,14 +1006,14 @@ SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = 19 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 19 + rand()
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Warning 1292 Incorrect datetime value: ' garbage '
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and <cache>(length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and <cache>(octet_length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -1038,7 +1038,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.0
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME(6));;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00.000000'),('2001-01-01 00:00:01.000000');
@@ -1063,7 +1063,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.0
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00.000000')) = 40 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00.000000')) = 40 + rand()
DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
CREATE TABLE t1 (a DATETIME);;
@@ -1089,7 +1089,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = 40 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 40 + rand()
DROP TABLE t1;
#
# MDEV-8795 Equal expression propagation does not work for temporal literals
@@ -1199,3 +1199,24 @@ DROP TABLE t1;
#
# End of 10.2 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-11331 Wrong result for INSERT INTO t1 (datetime_field) VALUES (hybrid_function_of_TIME_data_type)
+#
+SET timestamp=UNIX_TIMESTAMP('2001-02-03 10:00:00');
+CREATE TABLE t1 (a DATETIME);
+INSERT INTO t1 VALUES (TIME'10:20:30');
+INSERT INTO t1 VALUES (COALESCE(TIME'10:20:30'));
+INSERT INTO t1 VALUES (LEAST(TIME'10:20:30',TIME'10:20:30'));
+SELECT * FROM t1;
+a
+2001-02-03 10:20:30
+2001-02-03 10:20:30
+2001-02-03 10:20:30
+DROP TABLE t1;
+SET timestamp=DEFAULT;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/type_datetime_hires.result b/mysql-test/r/type_datetime_hires.result
index 50354430e3f..38e2c2a5ac8 100644
--- a/mysql-test/r/type_datetime_hires.result
+++ b/mysql-test/r/type_datetime_hires.result
@@ -131,18 +131,18 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` datetime(4) DEFAULT NULL,
- `a+0` decimal(25,4) DEFAULT NULL,
- `a-1` decimal(25,4) DEFAULT NULL,
- `a*1` decimal(25,4) DEFAULT NULL,
- `a/2` decimal(28,8) DEFAULT NULL
+ `a+0` decimal(19,4) DEFAULT NULL,
+ `a-1` decimal(19,4) DEFAULT NULL,
+ `a*1` decimal(19,4) DEFAULT NULL,
+ `a/2` decimal(22,8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`max(a)` datetime(4) DEFAULT NULL,
`min(a)` datetime(4) DEFAULT NULL,
- `sum(a)` decimal(46,4) DEFAULT NULL,
- `avg(a)` decimal(28,8) DEFAULT NULL
+ `sum(a)` decimal(40,4) DEFAULT NULL,
+ `avg(a)` decimal(22,8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2, t3;
create table t1 (f0_datetime datetime(0), f1_datetime datetime(1), f2_datetime datetime(2), f3_datetime datetime(3), f4_datetime datetime(4), f5_datetime datetime(5), f6_datetime datetime(6));
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 0ead4ec9aa2..2911e58fd88 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -1019,3 +1019,52 @@ cast('-0.0' as decimal(5,1)) < 0
#
# End of 5.5 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
+#
+# This creates the old DECIMAL. Will be fixed in MDEV-12574.
+CREATE TABLE t1 AS SELECT MAX(a) FROM t1dec102;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `MAX(a)` decimal(10,2)/*old*/ DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT COALESCE(a) FROM t1dec102;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `COALESCE(a)` decimal(10,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a BIGINT);
+CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` decimal(21,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+CREATE TABLE t1 (a MEDIUMINT);
+CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` decimal(10,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+CREATE TABLE t1 (a YEAR);
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1dec102;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` decimal(10,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+DROP TABLE t1dec102;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index 6ad75339847..02d71c6bd9f 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1803,13 +1803,18 @@ id c1 + 0 c1
4 0
DROP TABLE t1;
End of 4.1 tests
-create table t1(f1 set('a','b'), index(f1));
+SET sql_mode='';
+create table t1(f1 enum('a','b'), index(f1));
insert into t1 values(''),(''),('a'),('b');
+Warnings:
+Warning 1265 Data truncated for column 'f1' at row 1
+Warning 1265 Data truncated for column 'f1' at row 2
select * from t1 where f1='';
f1
drop table t1;
+SET sql_mode=DEFAULT;
CREATE TABLE t1 (c1 ENUM('a', '', 'b'));
INSERT INTO t1 (c1) VALUES ('b');
INSERT INTO t1 (c1) VALUES ('');
@@ -2219,3 +2224,90 @@ SELECT * FROM t1;
a
DROP TABLE t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
+#
+CREATE TABLE t1 (a ENUM('a','b','c','1'),KEY(a));
+INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
+EXPLAIN SELECT * FROM t1 WHERE a='xx';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='99999999';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a=100.1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='100';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='1x';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='1.0';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='1.1';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+DROP TABLE t1;
+#
+# MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
+#
+CREATE TABLE t1 (a ENUM('a'));
+# non-UNION + table column
+CREATE TABLE t2 AS SELECT (SELECT a FROM t1);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `(SELECT a FROM t1)` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+# UNION + table column
+CREATE TABLE t2 AS SELECT (SELECT a FROM t1 UNION SELECT NULL);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `(SELECT a FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+# UNION + SP variable
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va ENUM('a');
+CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `(SELECT va FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+# UNION + anchored SP variable
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va TYPE OF t1.a;
+CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `(SELECT va FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 43aed60749e..9a92ff21e9f 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -232,12 +232,12 @@ insert into t2 values ("1.23456780");
create table t3 select * from t2 union select * from t1;
select * from t3;
d
-1.2345678
-100000000
+1.234567800
+100000000.000000000
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `d` double DEFAULT NULL
+ `d` double(18,9) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2, t3;
create table t1 select 105213674794682365.00 + 0.0 x;
@@ -562,7 +562,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=100e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 100e0 and <cache>(length(100)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 100e0 and <cache>(octet_length(100)) <> rand()
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
@@ -582,7 +582,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10e0 and <cache>(length(1.1)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10e0 and <cache>(octet_length(1.1)) <> rand()
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
@@ -602,7 +602,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10e0 and <cache>(length(1.10)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10e0 and <cache>(octet_length(1.10)) <> rand()
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
@@ -622,7 +622,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10e0 and <cache>(length(1.100)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10e0 and <cache>(octet_length(1.100)) <> rand()
DROP TABLE t1;
#
# MDEV-8741 Equal field propagation leaves some remainders after simplifying WHERE zerofill_column=2010 AND zerofill_column>=2010
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index ab0e2dbc71d..ba84ff50504 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -2086,7 +2086,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10 and <cache>(length(1.1)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10 and <cache>(octet_length(1.1)) <> rand()
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
@@ -2106,7 +2106,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10 and <cache>(length(1.10)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10 and <cache>(octet_length(1.10)) <> rand()
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
@@ -2126,7 +2126,7 @@ SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10 and <cache>(length(1.100)) <> rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1.10 and <cache>(octet_length(1.100)) <> rand()
DROP TABLE t1;
#
# MDEV-8741 Equal field propagation leaves some remainders after simplifying WHERE zerofill_column=2010 AND zerofill_column>=2010
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index fe7392c758f..784a394d8b5 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -272,7 +272,7 @@ drop table t2;
create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(11) unsigned NULL NO PRI NULL #
+auto bigint(11) unsigned NULL NO PRI NULL #
t1 int(1) NULL NO NULL #
t2 varchar(1) latin1_swedish_ci NO NULL #
t3 varchar(256) latin1_swedish_ci YES NULL #
diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result
index 742ee5a33e9..1258de317ec 100644
--- a/mysql-test/r/type_set.result
+++ b/mysql-test/r/type_set.result
@@ -316,3 +316,39 @@ DROP TABLE t1;
#
# End of 10.1 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
+#
+CREATE TABLE t1 (a SET('a','b','c','1'),KEY(a));
+INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
+EXPLAIN SELECT * FROM t1 WHERE a='xx';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='99999999';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a=100.1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='100';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='1x';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='1.0';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+EXPLAIN SELECT * FROM t1 WHERE a='1.1';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+DROP TABLE t1;
diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result
index 2aabd98229d..1600732cec3 100644
--- a/mysql-test/r/type_time.result
+++ b/mysql-test/r/type_time.result
@@ -221,7 +221,7 @@ MAX(t0)+1
101011
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
-MAX(t0)+1 bigint(12) YES NULL
+MAX(t0)+1 int(9) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
@@ -234,7 +234,7 @@ MAX(t0)+1.1
101011.1
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
-MAX(t0)+1.1 decimal(12,1) YES NULL
+MAX(t0)+1.1 decimal(9,1) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 TIME);
INSERT INTO t1 VALUES ('10:10:10');
@@ -260,7 +260,7 @@ MAX(t1)+1
101011.0
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
-MAX(t1)+1 decimal(13,1) YES NULL
+MAX(t1)+1 decimal(9,1) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
@@ -273,7 +273,7 @@ MAX(t0)+1
20010101101011
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
-MAX(t0)+1 bigint(21) YES NULL
+MAX(t0)+1 bigint(16) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
@@ -286,7 +286,7 @@ MAX(t0)+1.1
20010101101011.1
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
-MAX(t0)+1.1 decimal(21,1) YES NULL
+MAX(t0)+1.1 decimal(16,1) YES NULL
DROP TABLE t2,t1;
CREATE TABLE t1 (t0 DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 10:10:10');
@@ -312,7 +312,7 @@ MAX(t1)+1
20010101101011.0
SHOW COLUMNS FROM t2;
Field Type Null Key Default Extra
-MAX(t1)+1 decimal(22,1) YES NULL
+MAX(t1)+1 decimal(16,1) YES NULL
DROP TABLE t2,t1;
#
# MDEV-4858 Wrong results for a huge unsigned value inserted into a TIME column
@@ -424,7 +424,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Warning 1292 Truncated incorrect time value: '00:00:00x'
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(length(TIME'00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(octet_length(TIME'00:00:00')) = 30 + rand()
DROP TABLE t1;
# Trailing fractional digits in string literals
CREATE TABLE t1 (a TIME);
@@ -447,7 +447,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='00:00:00.000000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(length(TIME'00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(octet_length(TIME'00:00:00')) = 30 + rand()
DROP TABLE t1;
# Trailing fractional digits in temporal literals
CREATE TABLE t1 (a TIME);
@@ -470,7 +470,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00.000000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00.000000' and <cache>(length(TIME'00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00.000000' and <cache>(octet_length(TIME'00:00:00')) = 30 + rand()
DROP TABLE t1;
# Trailing fractional digits in temporal literals, same precision
CREATE TABLE t1 (a TIME(6));
@@ -490,7 +490,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00.000000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00.000000' and <cache>(length(TIME'00:00:00.000000')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00.000000' and <cache>(octet_length(TIME'00:00:00.000000')) = 30 + rand()
DROP TABLE t1;
# Leading spaces in string literals
CREATE TABLE t1 (a TIME);
@@ -513,7 +513,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(length(TIME'00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(octet_length(TIME'00:00:00')) = 30 + rand()
DROP TABLE t1;
# Numeric format in string literals
CREATE TABLE t1 (a TIME);
@@ -536,7 +536,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='000000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(length(TIME'00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:00' and <cache>(octet_length(TIME'00:00:00')) = 30 + rand()
DROP TABLE t1;
#
# MDEV-8766 Wrong result for SELECT..WHERE LENGTH(time_column)=8 AND time_column=TIMESTAMP'2001-01-01 10:20:31'
@@ -565,7 +565,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 10:20:31';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIMESTAMP literal with a bigger scale and fractional second truncation
# Ok to propagate with precision truncation
@@ -589,7 +589,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 10:20:31.1
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIMESTAMP literal with a bigger scale and no fractional second truncation
# Ok to propagate
@@ -615,7 +615,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 10:20:31.0
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIMESTAMP literal with a smaller scale
# Ok to propagate
@@ -638,7 +638,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 10:20:31.1
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(length(TIME'10:20:31.123000')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(octet_length(TIME'10:20:31.123000')) = 30 + rand()
DROP TABLE t1;
# TIME literal with a bigger scale and fractional second truncation
# Ok to propagate with precision truncation
@@ -662,7 +662,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'10:20:31.123';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIME literal with a bigger scale and no fractional second truncation
# Ok to propagate
@@ -688,7 +688,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'10:20:31.000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.000' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.000' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIME literal with a smaller scale
# Ok to propagate
@@ -711,7 +711,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'10:20:31.123';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123' and <cache>(length(TIME'10:20:31.123000')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123' and <cache>(octet_length(TIME'10:20:31.123000')) = 30 + rand()
DROP TABLE t1;
# TIME-alike string literal with a bigger scale and fractional second truncation
# Ok to propagate with precision truncation
@@ -735,7 +735,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='10:20:31.123';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIME-alike string literal with a bigger scale and no fractional second truncation
# Ok to propagate
@@ -761,7 +761,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='10:20:31.000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31' and <cache>(length(TIME'10:20:31')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31' and <cache>(octet_length(TIME'10:20:31')) = 30 + rand()
DROP TABLE t1;
# TIME-alike string literal with a smaller scale
# Ok to propagate
@@ -784,7 +784,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='10:20:31.123';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(length(TIME'10:20:31.123000')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:31.123000' and <cache>(octet_length(TIME'10:20:31.123000')) = 30 + rand()
DROP TABLE t1;
SET timestamp=DEFAULT;
SET @@old_mode=zero_date_time_cast;
@@ -821,7 +821,7 @@ SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-00 10:20:30' AND LENGTH(a)=30+RAND();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:30' and <cache>(length(TIME'10:20:30')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:30' and <cache>(octet_length(TIME'10:20:30')) = 30 + rand()
# Old mode, TIMESTAMP literal, zon-zero YYYYMMDD, no propagation
SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-01 10:20:30';
a
@@ -834,13 +834,13 @@ SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-01 10:20:30' AND LENGTH(a)=8;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-01 10:20:30' and length(`test`.`t1`.`a`) = 8
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-01 10:20:30' and octet_length(`test`.`t1`.`a`) = 8
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-01 10:20:30' AND LENGTH(a)=30+RAND();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-01 10:20:30' and length(`test`.`t1`.`a`) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-01 10:20:30' and octet_length(`test`.`t1`.`a`) = 30 + rand()
# Old mode, TIMESTAMP-alike string literal, zero YYYYMMDD, Ok to propagate
SELECT * FROM t1 WHERE a='0000-00-00 10:20:30';
a
@@ -859,7 +859,7 @@ SELECT * FROM t1 WHERE a='0000-00-00 10:20:30' AND LENGTH(a)=30+RAND();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:30' and <cache>(length(TIME'10:20:30')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'10:20:30' and <cache>(octet_length(TIME'10:20:30')) = 30 + rand()
# Old mode, TIMESTAMP-alike literal, zon-zero YYYYMMDD, no propagation
SELECT * FROM t1 WHERE a='0000-00-01 10:20:30';
a
@@ -872,13 +872,13 @@ SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=8;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '0000-00-01 10:20:30' and length(`test`.`t1`.`a`) = 8
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '0000-00-01 10:20:30' and octet_length(`test`.`t1`.`a`) = 8
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a='0000-00-01 10:20:30' AND LENGTH(a)=30+RAND();
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '0000-00-01 10:20:30' and length(`test`.`t1`.`a`) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '0000-00-01 10:20:30' and octet_length(`test`.`t1`.`a`) = 30 + rand()
DROP TABLE t1;
SET @@old_mode=DEFAULT;
#
@@ -1247,3 +1247,25 @@ DROP TABLE t1,t2;
#
# End of 10.2 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
+#
+SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31');
+TIME'10:20:30' IN (102030,TIME'10:20:31')
+1
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
+TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
+1
+CREATE TABLE t1 (a TIME);
+INSERT INTO t1 VALUES ('10:20:30'),('10:20:31'),('10:20:32');
+SELECT a FROM t1 WHERE a IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') ORDER BY a;
+a
+10:20:30
+10:20:31
+10:20:32
+DROP TABLE t1;
+SET timestamp=DEFAULT;
diff --git a/mysql-test/r/type_time_hires.result b/mysql-test/r/type_time_hires.result
index a9345a7e83f..47185116bea 100644
--- a/mysql-test/r/type_time_hires.result
+++ b/mysql-test/r/type_time_hires.result
@@ -145,18 +145,18 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` time(4) DEFAULT NULL,
- `a+0` decimal(16,4) DEFAULT NULL,
- `a-1` decimal(16,4) DEFAULT NULL,
- `a*1` decimal(16,4) DEFAULT NULL,
- `a/2` decimal(19,8) DEFAULT NULL
+ `a+0` decimal(12,4) DEFAULT NULL,
+ `a-1` decimal(12,4) DEFAULT NULL,
+ `a*1` decimal(12,4) DEFAULT NULL,
+ `a/2` decimal(15,8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`max(a)` time(4) DEFAULT NULL,
`min(a)` time(4) DEFAULT NULL,
- `sum(a)` decimal(37,4) DEFAULT NULL,
- `avg(a)` decimal(19,8) DEFAULT NULL
+ `sum(a)` decimal(33,4) DEFAULT NULL,
+ `avg(a)` decimal(15,8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2, t3;
create table t1 (f0_time time(0), f1_time time(1), f2_time time(2), f3_time time(3), f4_time time(4), f5_time time(5), f6_time time(6));
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 20523dc1791..b0405bc4ad7 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -840,7 +840,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) <> 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -862,14 +862,14 @@ SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = 19 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 19 + rand()
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Warning 1292 Incorrect datetime value: ' garbage '
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and <cache>(length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and <cache>(octet_length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
@@ -894,7 +894,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.0
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = 30 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 30 + rand()
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP(6));;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00.000000'),('2001-01-01 00:00:01.000000');
@@ -919,7 +919,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.0
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00.000000')) = 40 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00.000000')) = 40 + rand()
DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
CREATE TABLE t1 (a TIMESTAMP);;
@@ -945,8 +945,72 @@ SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = 40 + rand()
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00' and <cache>(octet_length(TIMESTAMP'2001-01-01 00:00:00')) = 40 + rand()
DROP TABLE t1;
#
# End of 10.1 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-11333 MDEV-11333 Expect "Impossible where condition" for WHERE timestamp_field>=DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR)
+#
+SELECT DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR);
+DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR)
+NULL
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
+CREATE TABLE t1 (a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+EXPLAIN SELECT * FROM t1 WHERE a >= DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
+EXPLAIN SELECT * FROM t1 WHERE a >= COALESCE(DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Warning 1441 Datetime function: datetime field overflow
+DROP TABLE t1;
+#
+# MDEV-11482 Incorrect result for (time_expr BETWEEN timestamp_exp1 AND timestamp_expr2)
+#
+SET @@sql_mode=DEFAULT;
+SET @@timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
+CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP);
+INSERT INTO t1 VALUES ('2001-01-01 00:00:00','2001-01-01 23:59:59');
+SELECT * FROM t1 WHERE TIME'10:20:30' BETWEEN a and b;
+a b
+2001-01-01 00:00:00 2001-01-01 23:59:59
+DROP TABLE t1;
+SET @@timestamp=DEFAULT;
+#
+# MDEV-12582 Wrong data type for CREATE..SELECT MAX(COALESCE(timestamp_column))
+#
+CREATE TABLE t1 (a TIMESTAMP);
+CREATE TABLE t2 AS SELECT
+MAX(a),
+COALESCE(a),
+COALESCE(MAX(a)),
+MAX(COALESCE(a))
+FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `MAX(a)` timestamp NULL DEFAULT NULL,
+ `COALESCE(a)` timestamp NULL DEFAULT NULL,
+ `COALESCE(MAX(a))` timestamp NULL DEFAULT NULL,
+ `MAX(COALESCE(a))` timestamp NULL DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/type_timestamp_hires.result b/mysql-test/r/type_timestamp_hires.result
index 7179277aa9a..fa6adc075ed 100644
--- a/mysql-test/r/type_timestamp_hires.result
+++ b/mysql-test/r/type_timestamp_hires.result
@@ -131,18 +131,18 @@ show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` timestamp(4) NOT NULL DEFAULT current_timestamp(4) ON UPDATE current_timestamp(4),
- `a+0` decimal(25,4) NOT NULL,
- `a-1` decimal(25,4) NOT NULL,
- `a*1` decimal(25,4) NOT NULL,
- `a/2` decimal(28,8) DEFAULT NULL
+ `a+0` decimal(19,4) NOT NULL,
+ `a-1` decimal(19,4) NOT NULL,
+ `a*1` decimal(19,4) NOT NULL,
+ `a/2` decimal(22,8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`max(a)` timestamp(4) NULL DEFAULT NULL,
`min(a)` timestamp(4) NULL DEFAULT NULL,
- `sum(a)` decimal(46,4) DEFAULT NULL,
- `avg(a)` decimal(28,8) DEFAULT NULL
+ `sum(a)` decimal(40,4) DEFAULT NULL,
+ `avg(a)` decimal(22,8) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2, t3;
create table t1 (f0_timestamp timestamp(0), f1_timestamp timestamp(1), f2_timestamp timestamp(2), f3_timestamp timestamp(3), f4_timestamp timestamp(4), f5_timestamp timestamp(5), f6_timestamp timestamp(6));
diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result
index 98aa2b50fc6..6af6b167511 100644
--- a/mysql-test/r/udf.result
+++ b/mysql-test/r/udf.result
@@ -4,7 +4,7 @@ CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
ERROR HY000: Can't find symbol 'myfunc_nonexist' in library
CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
-CREATE FUNCTION sequence RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
CREATE FUNCTION lookup RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
CREATE FUNCTION reverse_lookup
RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
@@ -226,7 +226,7 @@ DROP FUNCTION myfunc_double;
DROP FUNCTION myfunc_nonexist;
ERROR 42000: FUNCTION test.myfunc_nonexist does not exist
DROP FUNCTION myfunc_int;
-DROP FUNCTION sequence;
+DROP FUNCTION udf_sequence;
DROP FUNCTION lookup;
DROP FUNCTION reverse_lookup;
DROP FUNCTION avgcost;
@@ -340,32 +340,32 @@ DROP FUNCTION check_const_len;
DROP PROCEDURE check_const_len_sp;
DROP TRIGGER check_const_len_trigger;
DROP TABLE const_len_bug;
-CREATE FUNCTION sequence RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
+CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT PRIMARY KEY);
INSERT INTO t1 VALUES (4),(3),(2),(1);
INSERT INTO t2 SELECT * FROM t1;
-SELECT sequence() AS seq, a FROM t1 ORDER BY seq ASC;
+SELECT udf_sequence() AS seq, a FROM t1 ORDER BY seq ASC;
seq a
1 4
2 3
3 2
4 1
-SELECT sequence() AS seq, a FROM t1 ORDER BY seq DESC;
+SELECT udf_sequence() AS seq, a FROM t1 ORDER BY seq DESC;
seq a
4 1
3 2
2 3
1 4
-SELECT * FROM t1 WHERE a = sequence();
+SELECT * FROM t1 WHERE a = udf_sequence();
a
-SELECT * FROM t2 WHERE a = sequence();
+SELECT * FROM t2 WHERE a = udf_sequence();
a
1
2
3
4
-DROP FUNCTION sequence;
+DROP FUNCTION udf_sequence;
DROP TABLE t1,t2;
drop function if exists test.metaphon;
drop function if exists metaphon;
diff --git a/mysql-test/r/udf_notembedded.result b/mysql-test/r/udf_notembedded.result
index 3fdcdbbe9d3..377af563d3e 100644
--- a/mysql-test/r/udf_notembedded.result
+++ b/mysql-test/r/udf_notembedded.result
@@ -1,6 +1,6 @@
-create function sequence returns integer soname "UDF_EXAMPLE_LIB";
-create table t1 (n int key not null auto_increment, msg int as (sequence()) virtual);
+create function udf_sequence returns integer soname "UDF_EXAMPLE_LIB";
+create table t1 (n int key not null auto_increment, msg int as (udf_sequence()) virtual);
select * from t1;
n msg
drop table t1;
-drop function sequence;
+drop function udf_sequence;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 77fea060d32..956703237a1 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -88,7 +88,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t2 ALL NULL NULL NULL NULL 4 100.00 Using filesort
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` limit 2) union all (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`a` limit 1) order by `b` desc
+Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` limit 2) union all (/* select#2 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`a` limit 1) order by `b` desc
select count(*) from (
(select a,b from t1 limit 2) union all (select a,b from t2 order by a)) q;
count(*)
@@ -544,7 +544,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t2 const PRIMARY PRIMARY 4 const 1 100.00
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select 1 AS `a`,1 AS `b` from `test`.`t1` where 1) union (select 1 AS `a`,10 AS `b` from `test`.`t2` where 1)
+Note 1003 (/* select#1 */ select 1 AS `a`,1 AS `b` from `test`.`t1` where 1) union (/* select#2 */ select 1 AS `a`,10 AS `b` from `test`.`t2` where 1)
(select * from t1 where a=5) union (select * from t2 where a=1);
a b
1 10
@@ -852,7 +852,7 @@ select * from t1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `1` bigint(20) NOT NULL DEFAULT 0
+ `1` int(2) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 select _latin1"test" union select _latin2"testt" ;
@@ -1449,6 +1449,28 @@ t2 CREATE TABLE `t2` (
`f8` mediumtext CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2;
+CREATE TABLE t1
+(
+c_varchar varchar(1) character set utf8 collate utf8_general_ci,
+c_tinytext tinytext,
+c_text text,
+c_mediumtext mediumtext,
+c_longtext longtext
+);
+CREATE TABLE t2 AS
+SELECT c_tinytext, c_text, c_mediumtext, c_longtext FROM t1
+UNION
+SELECT c_varchar, c_varchar, c_varchar, c_varchar FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `c_tinytext` text CHARACTER SET utf8 DEFAULT NULL,
+ `c_text` mediumtext CHARACTER SET utf8 DEFAULT NULL,
+ `c_mediumtext` longtext CHARACTER SET utf8 DEFAULT NULL,
+ `c_longtext` longtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
(select avg(1)) union (select avg(1)) union (select avg(1)) union
(select avg(1)) union (select avg(1)) union (select avg(1)) union
(select avg(1)) union (select avg(1)) union (select avg(1)) union
@@ -1586,7 +1608,7 @@ NULL binary(0) YES NULL
CREATE TABLE t5 SELECT NULL UNION SELECT NULL;
DESC t5;
Field Type Null Key Default Extra
-NULL binary(0) YES NULL
+NULL null YES NULL
CREATE TABLE t6
SELECT * FROM (SELECT * FROM (SELECT NULL)a) b UNION SELECT a FROM t1;
DESC t6;
@@ -1616,7 +1638,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t1 system NULL NULL NULL NULL 0 0.00 const row not found
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 select NULL AS `a` from `test`.`t1` union select NULL AS `a` from `test`.`t1` order by `a`
+Note 1003 /* select#1 */ select NULL AS `a` from `test`.`t1` union /* select#2 */ select NULL AS `a` from `test`.`t1` order by `a`
DROP TABLE t1;
#
# Bug#32858: Error: "Incorrect usage of UNION and INTO" does not take
@@ -1670,7 +1692,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t1 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by `a` + 12
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by `a` + 12
# Should not crash
SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12;
a
@@ -1685,7 +1707,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t1 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (match `a` against ('+abc' in boolean mode))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (match `a` against ('+abc' in boolean mode))
# Should not crash
SELECT * FROM t1 UNION SELECT * FROM t1
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
@@ -1709,7 +1731,7 @@ NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #-1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by <expr_cache><`a`>((select `a` from `test`.`t2` where `test`.`t2`.`b` = 12))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by <expr_cache><`a`>((/* select#3 */ select `a` from `test`.`t2` where `test`.`t2`.`b` = 12))
# Should not crash
SELECT * FROM t1 UNION SELECT * FROM t1
ORDER BY (SELECT a FROM t2 WHERE b = 12);
@@ -2156,7 +2178,6 @@ WHERE t1_2.b NOT IN ( SELECT 4 UNION ALL SELECT 5 );
a b a b
1 1 1 1
DROP TABLE t1;
-#
# Bug mdev-12788: UNION ALL + impossible having for derived
# with IN subquery in WHERE
#
@@ -2184,5 +2205,242 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
Warnings:
-Note 1003 select 1 AS `1`,2 AS `2` union all select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 1 group by 1 having 0
+Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 1 group by 1 having 0
DROP TABLE t1,t2;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12619 UNION creates excessive integer column types for integer literals
+#
+CREATE TABLE t1 AS SELECT 1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `1` int(1) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT 1 UNION SELECT 1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `1` int(1) NOT NULL DEFAULT 0
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT * FROM (SELECT 1 UNION SELECT 1) AS t0;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `1` int(1) NOT NULL DEFAULT 0
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# MDEV-9495 Wrong field type for a UNION of a signed and an unsigned INT expression
+#
+CREATE TABLE t1 (a INT, b INT UNSIGNED);
+INSERT INTO t1 VALUES (0x7FFFFFFF,0xFFFFFFFF);
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2 ORDER BY a;
+a
+2147483647
+4294967295
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT COALESCE(a,b), COALESCE(b,a) FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `COALESCE(a,b)` decimal(10,0) DEFAULT NULL,
+ `COALESCE(b,a)` decimal(10,0) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t2;
+COALESCE(a,b) COALESCE(b,a)
+2147483647 4294967295
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-9497 UNION and COALESCE produce different field types for DECIMAL+INT
+#
+CREATE TABLE t1 AS SELECT COALESCE(10.1,CAST(10 AS UNSIGNED)) AS a;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` decimal(3,1) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT 10.1 AS a UNION SELECT CAST(10 AS UNSIGNED);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` decimal(3,1) NOT NULL DEFAULT 0.0
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# MDEV-12594 UNION between fixed length double columns does not always preserve scale
+#
+CREATE TABLE t1 (a FLOAT(20,4), b FLOAT(20,3), c FLOAT(20,4));
+INSERT INTO t1 VALUES (1111,2222,3333);
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` float(20,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE OR REPLACE TABLE t2 SELECT a FROM t1 UNION SELECT c FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` float(20,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE OR REPLACE TABLE t2 SELECT b FROM t1 UNION SELECT b FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `b` float(20,3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE OR REPLACE TABLE t2 SELECT c FROM t1 UNION SELECT c FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `c` float(20,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE OR REPLACE TABLE t2 SELECT c FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `c` float(20,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE OR REPLACE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` float(21,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE OR REPLACE TABLE t2 AS SELECT b FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `b` float(21,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+# Corner case
+CREATE TABLE t1 (a FLOAT(255,4), b FLOAT(255,3));
+INSERT INTO t1 VALUES (1111,2222);
+CREATE OR REPLACE TABLE t2 AS SELECT b FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `b` float(255,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-12595 UNION converts INT to BIGINT
+#
+CREATE TABLE t1 AS SELECT
+1,
+-1,
+COALESCE(1,1),
+COALESCE(-1,-1),
+COALESCE(1,-1),
+COALESCE(-1,1);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `1` int(1) NOT NULL,
+ `-1` int(2) NOT NULL,
+ `COALESCE(1,1)` int(1) NOT NULL,
+ `COALESCE(-1,-1)` int(2) NOT NULL,
+ `COALESCE(1,-1)` int(2) NOT NULL,
+ `COALESCE(-1,1)` int(2) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT 1 AS c1,1 AS c2,-1 AS c3,-1 AS c4 UNION SELECT 1,-1,1,-1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` int(1) NOT NULL DEFAULT 0,
+ `c2` int(2) NOT NULL DEFAULT 0,
+ `c3` int(2) NOT NULL DEFAULT 0,
+ `c4` int(2) NOT NULL DEFAULT 0
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# MDEV-12599 UNION is not symmetric when mixing INT and CHAR
+#
+CREATE OR REPLACE TABLE t1 AS SELECT 1 AS c1, 'a' AS c2 UNION SELECT 'a', 1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(1) NOT NULL DEFAULT '',
+ `c2` varchar(1) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT 11112222 AS c1, 'a' AS c2 UNION SELECT 'a', 11112222;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(8) NOT NULL DEFAULT '',
+ `c2` varchar(8) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT 111122223333 AS c1, 'a' AS c2 UNION SELECT 'a', 111122223333;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(12) NOT NULL DEFAULT '',
+ `c2` varchar(12) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT 1111222233334444 AS c1, 'a' AS c2 UNION SELECT 'a', 1111222233334444;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(16) NOT NULL DEFAULT '',
+ `c2` varchar(16) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT(3), b VARCHAR(1));
+CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(11) DEFAULT NULL,
+ `b` varchar(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+CREATE TABLE t1 (a BIGINT(3), b VARCHAR(1));
+CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(20) DEFAULT NULL,
+ `b` varchar(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+CREATE TABLE t1 (a BIGINT(12), b VARCHAR(1));
+CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(20) DEFAULT NULL,
+ `b` varchar(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index e01d4f1a54b..0dd8b80a568 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -570,3 +570,22 @@ End of 5.5 tests
#
set @var= repeat('a',20000);
1
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12859 Out-of-range error for CREATE..SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM..
+#
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE OR REPLACE TABLE t1 AS
+SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM '2001-01-01 11:22:33.999999') AS c1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1
+2233999999
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/r/userstat.result b/mysql-test/r/userstat.result
index 37d07439fee..1db891e0184 100644
--- a/mysql-test/r/userstat.result
+++ b/mysql-test/r/userstat.result
@@ -128,6 +128,7 @@ Handler_read_rnd_next 5
Handler_rollback 2
Handler_savepoint 0
Handler_savepoint_rollback 0
+Handler_tmp_delete 0
Handler_tmp_update 0
Handler_tmp_write 0
Handler_update 5
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index bca59b5225a..676432690b4 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -672,9 +672,9 @@ select @a, @b;
@a @b
2 1
set @@global.global.key_buffer_size= 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+ERROR HY000: Unknown structured system variable or ROW routine variable 'global'
set GLOBAL global.key_buffer_size= 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+ERROR HY000: Unknown structured system variable or ROW routine variable 'global'
SELECT @@global.global.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size' at line 1
SELECT @@global.session.key_buffer_size;
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 1fae4e6ec9f..ef2e0935592 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -41,7 +41,7 @@ show create view v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`b` + 1 AS `c` from `t1` latin1 latin1_swedish_ci
show create view t1;
-ERROR HY000: 'test.t1' is not VIEW
+ERROR HY000: 'test.t1' is not of type 'VIEW'
drop table t1;
select a from v1;
ERROR 42S22: Unknown column 'a' in 'field list'
@@ -72,7 +72,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v2`.`c` AS `c` from `test`.`v2`
+Note 1003 /* select#1 */ select `v2`.`c` AS `c` from `test`.`v2`
create view v3 (c) as select a+1 from v1;
ERROR 42S22: Unknown column 'a' in 'field list'
create view v3 (c) as select b+1 from v1;
@@ -104,7 +104,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED <derived3> ALL NULL NULL NULL NULL 5 100.00
3 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v4`.`c` AS `c` from `test`.`v4`
+Note 1003 /* select#1 */ select `v4`.`c` AS `c` from `test`.`v4`
create view v5 (c) as select c+1 from v2;
select c from v5;
c
@@ -118,7 +118,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5 100.00
3 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v2`.`c` + 1 AS `c` from `test`.`v2`
+Note 1003 /* select#1 */ select `v2`.`c` + 1 AS `c` from `test`.`v2`
create algorithm=temptable view v6 (c) as select c+1 from v1;
select c from v6;
c
@@ -132,7 +132,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v6`.`c` AS `c` from `test`.`v6`
+Note 1003 /* select#1 */ select `v6`.`c` AS `c` from `test`.`v6`
show tables;
Tables_in_test
t1
@@ -197,9 +197,9 @@ c d
2 5
3 10
drop view v100;
-ERROR 42S02: Unknown table 'test.v100'
+ERROR 42S02: Unknown VIEW: 'test.v100'
drop view t1;
-ERROR HY000: 'test.t1' is not VIEW
+ERROR HY000: 'test.t1' is not of type 'VIEW'
drop table v1;
ERROR 42S02: 'test.v1' is a view
drop view v1,v2;
@@ -675,7 +675,7 @@ drop view v1;
create table t1 (col1 int,col2 char(22));
create view v1 as select * from t1;
create index i1 on v1 (col1);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
drop view v1;
drop table t1;
CREATE VIEW v1 (f1,f2,f3,f4) AS SELECT connection_id(), pi(), current_user(), version();
@@ -993,12 +993,6 @@ update v3 set v3.col1 = (select max(col1) from v2);
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v3'
update v3 set v3.col1 = (select max(col1) from v3);
ERROR HY000: Table 'v3' is specified twice, both as a target for 'UPDATE' and as a separate source for data
-delete from v2 where col1 = (select max(col1) from v1);
-ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'
-delete from v2 where col1 = (select max(col1) from t1);
-ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v2'
-delete from v2 where col1 = (select max(col1) from v2);
-ERROR HY000: Table 'v2' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'
delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
@@ -1061,7 +1055,7 @@ drop table t1,t2,t3;
create table t1 (s1 int);
create view v1 as select * from t1;
handler v1 open as xx;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
drop view v1;
drop table t1;
create table t1(a int);
@@ -2268,12 +2262,32 @@ create table t1 (s1 int);
create view abc as select * from t1 as abc;
drop table t1;
drop view abc;
+flush status;
create table t1(f1 char(1));
create view v1 as select * from t1;
-select * from (select f1 as f2 from v1) v where v.f2='a';
-f2
+select * from (select f1 as f2, f1 as f3 from v1) v where v.f2='a';
+f2 f3
+show status like "Created_tmp%";
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 0
drop view v1;
drop table t1;
+set @tmp=@@optimizer_switch;
+set @@optimizer_switch='derived_merge=OFF';
+create table t1(f1 char(1));
+create view v1 as select * from t1;
+select * from (select f1 as f2, f1 as f3 from v1) v where v.f2='a';
+f2 f3
+show status like "Created_tmp%";
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_files 0
+Created_tmp_tables 1
+drop view v1;
+drop table t1;
+set @@optimizer_switch=@tmp;
create view v1 as SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
select * from v1;
CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')
@@ -2425,28 +2439,28 @@ CREATE TABLE t1(id INT);
CREATE VIEW v1 AS SELECT id FROM t1;
OPTIMIZE TABLE v1;
Table Op Msg_type Msg_text
-test.v1 optimize Error 'test.v1' is not BASE TABLE
+test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE'
test.v1 optimize status Operation failed
ANALYZE TABLE v1;
Table Op Msg_type Msg_text
-test.v1 analyze Error 'test.v1' is not BASE TABLE
+test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE'
test.v1 analyze status Operation failed
REPAIR TABLE v1;
Table Op Msg_type Msg_text
-test.v1 repair Error 'test.v1' is not BASE TABLE
+test.v1 repair Error 'test.v1' is not of type 'BASE TABLE'
test.v1 repair status Operation failed
DROP TABLE t1;
OPTIMIZE TABLE v1;
Table Op Msg_type Msg_text
-test.v1 optimize Error 'test.v1' is not BASE TABLE
+test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE'
test.v1 optimize status Operation failed
ANALYZE TABLE v1;
Table Op Msg_type Msg_text
-test.v1 analyze Error 'test.v1' is not BASE TABLE
+test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE'
test.v1 analyze status Operation failed
REPAIR TABLE v1;
Table Op Msg_type Msg_text
-test.v1 repair Error 'test.v1' is not BASE TABLE
+test.v1 repair Error 'test.v1' is not of type 'BASE TABLE'
test.v1 repair status Operation failed
DROP VIEW v1;
create definer = current_user() sql security invoker view v1 as select 1;
@@ -2823,7 +2837,7 @@ CREATE TABLE t1 (i int, j int);
CREATE VIEW v1 AS SELECT COALESCE(i,j) FROM t1;
DESCRIBE v1;
Field Type Null Key Default Extra
-COALESCE(i,j) bigint(11) YES NULL
+COALESCE(i,j) int(11) YES NULL
CREATE TABLE t2 SELECT COALESCE(i,j) FROM t1;
DESCRIBE t2;
Field Type Null Key Default Extra
@@ -2894,13 +2908,13 @@ Tables_in_test
t1
v1
DROP VIEW v2,v1;
-ERROR 42S02: Unknown table 'test.v2'
+ERROR 42S02: Unknown VIEW: 'test.v2'
SHOW TABLES;
Tables_in_test
t1
CREATE VIEW v1 AS SELECT id FROM t1;
DROP VIEW t1,v1;
-ERROR HY000: 'test.t1' is not VIEW
+ERROR HY000: 'test.t1' is not of type 'VIEW'
SHOW TABLES;
Tables_in_test
t1
@@ -3686,7 +3700,7 @@ CREATE TABLE t1(c1 INT);
SELECT * FROM t1;
c1
ALTER ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW t1 (c2) AS SELECT (1);
-ERROR HY000: 'test.t1' is not VIEW
+ERROR HY000: 'test.t1' is not of type 'VIEW'
DROP TABLE t1;
@@ -3991,7 +4005,7 @@ drop procedure p;
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS SELECT a FROM t1;
ALTER TABLE v1;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
DROP VIEW v1;
DROP TABLE t1;
#
@@ -4562,7 +4576,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`a` = `test`.`t1`.`a`) where `test`.`t1`.`b` = 1 or `test`.`t1`.`a` = 'a' and length(`test`.`t1`.`a`) >= `test`.`t1`.`b`
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`a` = `test`.`t1`.`a`) where `test`.`t1`.`b` = 1 or `test`.`t1`.`a` = 'a' and octet_length(`test`.`t1`.`a`) >= `test`.`t1`.`b`
DROP VIEW v1;
DROP TABLE t1,t2;
# Bug#798625: duplicate of the previous one, but without crash
@@ -4643,7 +4657,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1926 View 'test'.'v2' ORDER BY clause ignored because there is other ORDER BY clause already
-Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f1` AS `f1` from `test`.`v1` join `test`.`v1` order by `v1`.`f1`
+Note 1003 /* select#1 */ select `v1`.`f1` AS `f1`,`v1`.`f1` AS `f1` from `test`.`v1` join `test`.`v1` order by `v1`.`f1`
DROP VIEW v1, v2;
DROP TABLE t1;
#
@@ -4669,7 +4683,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a`,10 AS `a` from `test`.`t1` where !<expr_cache><10,`test`.`t1`.`a`>(<in_optimizer>(10,<exists>(select NULL from `test`.`t4` where `test`.`t4`.`a` >= `test`.`t1`.`a` and trigcond(<cache>(10) = NULL or <cache>(NULL is null)) having trigcond(NULL is null))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,10 AS `a` from `test`.`t1` where !<expr_cache><10,`test`.`t1`.`a`>(<in_optimizer>(10,<exists>(/* select#2 */ select NULL from `test`.`t4` where `test`.`t4`.`a` >= `test`.`t1`.`a` and trigcond(<cache>(10) = NULL or <cache>(NULL is null)) having trigcond(NULL is null))))
SELECT * FROM t1, t2
WHERE t2.a NOT IN (SELECT t3.b FROM t3 RIGHT JOIN t4 ON (t4.a = t3.a)
WHERE t4.a >= t1.a);
@@ -4685,7 +4699,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'v1.a' of SELECT #2 was resolved in SELECT #1
-Note 1003 select `test`.`t1`.`a` AS `a`,10 AS `a` from `test`.`t1` where !<expr_cache><10,`test`.`t1`.`a`>(<in_optimizer>(10,<exists>(select NULL from `test`.`t4` where `test`.`t4`.`a` >= `test`.`t1`.`a` and trigcond(<cache>(10) = NULL or <cache>(NULL is null)) having trigcond(NULL is null))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,10 AS `a` from `test`.`t1` where !<expr_cache><10,`test`.`t1`.`a`>(<in_optimizer>(10,<exists>(/* select#2 */ select NULL from `test`.`t4` where `test`.`t4`.`a` >= `test`.`t1`.`a` and trigcond(<cache>(10) = NULL or <cache>(NULL is null)) having trigcond(NULL is null))))
SELECT * FROM v1, t2
WHERE t2.a NOT IN (SELECT t3.b FROM t3 RIGHT JOIN t4 ON (t4.a = t3.a)
WHERE t4.a >= v1.a);
@@ -4716,7 +4730,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
Note 1276 Field or reference 'test.t4.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 0 AS `c`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c` from `test`.`t4` where `test`.`t4`.`c` <= <expr_cache><`test`.`t4`.`b`>((select 0 from dual where 7 > `test`.`t4`.`b`))
+Note 1003 /* select#1 */ select 0 AS `c`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c` from `test`.`t4` where `test`.`t4`.`c` <= <expr_cache><`test`.`t4`.`b`>((/* select#2 */ select 0 from dual where 7 > `test`.`t4`.`b`))
SELECT * FROM t3 , t4
WHERE t4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
WHERE t2.b > t4.b);
@@ -4733,7 +4747,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Warnings:
Note 1276 Field or reference 'v4.b' of SELECT #2 was resolved in SELECT #1
-Note 1003 select 0 AS `c`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c` from `test`.`t4` where `test`.`t4`.`c` <= <expr_cache><`test`.`t4`.`b`>((select 0 from dual where 7 > `test`.`t4`.`b`))
+Note 1003 /* select#1 */ select 0 AS `c`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c` from `test`.`t4` where `test`.`t4`.`c` <= <expr_cache><`test`.`t4`.`b`>((/* select#2 */ select 0 from dual where 7 > `test`.`t4`.`b`))
SELECT * FROM t3, v4
WHERE v4.c <= (SELECT t2.e FROM t2 LEFT JOIN t1 ON ( t1.a = t2.d )
WHERE t2.b > v4.b);
@@ -5222,7 +5236,7 @@ CREATE TABLE t4 (i4 INT);
INSERT INTO t4 VALUES (1),(2);
DROP VIEW IF EXISTS v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
CREATE VIEW v1 AS select coalesce(j1,i3) AS v1_field1 from t2 join t3 left join t1 on ( i1 = i2 );
CREATE VIEW v2 AS select v1_field1 from t4 join v1;
prepare my_stmt from "select v1_field1 from v2";
@@ -5564,7 +5578,7 @@ create table t1 (a int, b int);
create view v1 as select a+b from t1;
alter table v1 check partition p1;
Table Op Msg_type Msg_text
-test.v1 check Error 'test.v1' is not BASE TABLE
+test.v1 check Error 'test.v1' is not of type 'BASE TABLE'
test.v1 check status Operation failed
drop view v1;
drop table t1;
@@ -5682,7 +5696,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `test`.`t1`.`a` AS `a`,(select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1`
select * from v1;
a c
1 2
@@ -5699,7 +5713,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a`
select * from t2, v1 where t2.a=v1.a;
a b a c
1 2 1 2
@@ -5718,7 +5732,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a`
select * from t1, v1 where t1.a=v1.a;
a b a c
1 2 1 2
@@ -5737,7 +5751,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`b` = (select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`b` = (/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`)
select * from t1, v1 where t1.b=v1.c;
a b a c
1 2 1 2
@@ -5755,7 +5769,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
-Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t2` join `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`a` = `test`.`t2`.`a`
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,(/* select#3 */ select max(`test`.`t2`.`b`) from `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a`) AS `c` from `test`.`t2` join `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`a` = `test`.`t2`.`a`
select * from t2, t1, v1 where t1.a=t2.a and t1.a=v1.a;
a b a b a c
1 2 1 2 1 2
@@ -6561,3 +6575,14 @@ DROP VIEW v;
#
# End of 10.2 tests
#
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-13197 Parser refactoring for CREATE VIEW,TRIGGER,SP,UDF,EVENT
+#
+ALTER VIEW IF NOT EXISTS v1 AS SELECT 1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'IF NOT EXISTS v1 AS SELECT 1' at line 1
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index 3f4f62dc935..5001f707f5a 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -353,6 +353,7 @@ ERROR 23000: Duplicate entry '11' for key 'a'
SHOW WARNINGS;
Level Code Message
+Note 4070 At line 4 in test.f1
Error 1062 Duplicate entry '11' for key 'a'
DROP TABLE t1;
diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result
index 7f8777ed491..eb4d612d398 100644
--- a/mysql-test/r/win.result
+++ b/mysql-test/r/win.result
@@ -3141,3 +3141,15 @@ sum(i) over (order by i) interval(sum(i) over (order by i), 10, 20)
33 2
63 2
drop table t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-13240 Wrong warning with MAX(datetime_field) OVER (...)
+#
+CREATE TABLE t1 (dt DATETIME);
+INSERT INTO t1 VALUES ('2017-05-17');
+SELECT MAX(dt) OVER (ORDER BY dt ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) FROM t1;
+MAX(dt) OVER (ORDER BY dt ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
+NULL
+DROP TABLE t1;
diff --git a/mysql-test/r/win_first_last_value.result b/mysql-test/r/win_first_last_value.result
index b8fab458249..9de394ef9e0 100644
--- a/mysql-test/r/win_first_last_value.result
+++ b/mysql-test/r/win_first_last_value.result
@@ -129,3 +129,17 @@ i fst_1f last_1f fst_1p1f fst_1p1f fst_2p1p fst_2p1p fst_1f2f fst_1f2f
9 9 10 8 10 7 8 10 10
10 10 10 9 10 8 9 NULL NULL
drop table t1;
+#
+# MDEV-12861 FIRST_VALUE() does not preserve the exact data type
+#
+CREATE TABLE t1 (a INT, b INT, c FLOAT);
+INSERT INTO t1 VALUES (1,1,1),(1,2,2),(2,1,1),(2,2,2);
+CREATE TABLE t2 AS SELECT a, FIRST_VALUE(b) OVER(), FIRST_VALUE(c) OVER() FROM t1 GROUP BY a;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `FIRST_VALUE(b) OVER()` int(11) DEFAULT NULL,
+ `FIRST_VALUE(c) OVER()` float DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2,t1;
diff --git a/mysql-test/r/win_insert_select.result b/mysql-test/r/win_insert_select.result
index c86576df6ae..5eddbf78713 100644
--- a/mysql-test/r/win_insert_select.result
+++ b/mysql-test/r/win_insert_select.result
@@ -1,7 +1,7 @@
CREATE TABLE t1 (c1 INT, c2 VARCHAR(30));
PREPARE populate_table FROM "INSERT into t1 values (1, 'manual_insert_1'),
(4, 'manual_insert_2')";
-INSERT INTO t1 SELECT row_number() over(), "should_have_0" FROM t1;
+INSERT INTO t1 SELECT row_number() over(), "should_have_NULL" FROM t1;
INSERT INTO t1 SELECT 1 + row_number() over(), "should_have_2" FROM t1;
EXECUTE populate_table;
INSERT INTO t1 SELECT 10 + row_number() over(), "should repeat 4 times [11-14]" FROM t1;
@@ -13,8 +13,8 @@ c1 c2
12 should repeat 4 times [11-14]
13 should repeat 4 times [11-14]
14 should repeat 4 times [11-14]
-0 should_have_0
2 should_have_2
+NULL should_have_NULL
DELETE FROM t1;
EXECUTE populate_table;
INSERT INTO t1
diff --git a/mysql-test/suite/archive/archive_gis.result b/mysql-test/suite/archive/archive_gis.result
index 6ee50fd3b85..71cdb72e4ce 100644
--- a/mysql-test/suite/archive/archive_gis.result
+++ b/mysql-test/suite/archive/archive_gis.result
@@ -507,8 +507,8 @@ down3,left3,right3,up3
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
equals
center
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-intersect
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+intersects
big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
overlaps
diff --git a/mysql-test/suite/binlog/r/binlog_stm_sp.result b/mysql-test/suite/binlog/r/binlog_stm_sp.result
new file mode 100644
index 00000000000..6c470517a93
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_stm_sp.result
@@ -0,0 +1,86 @@
+#
+# MDEV-11815 SP variables of temporal data types do not replicate correctly
+#
+CREATE TABLE t1(a INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE i INT DEFAULT 123;
+DECLARE b8 BIT(8) DEFAULT 0x61;
+DECLARE t0 TIME DEFAULT '01:01:01';
+DECLARE t6 TIME(6) DEFAULT '01:01:01.123456';
+DECLARE d DATE DEFAULT '2001-01-01';
+DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01';
+DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456';
+DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01';
+DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456';
+INSERT INTO t1 VALUES (i=0x61);
+INSERT INTO t1 VALUES (b8=0x61);
+INSERT INTO t1 VALUES (t0=10101);
+INSERT INTO t1 VALUES (t6=10101);
+INSERT INTO t1 VALUES (d=20010101);
+INSERT INTO t1 VALUES (dt0=20010101010101);
+INSERT INTO t1 VALUES (dt6=20010101010101);
+INSERT INTO t1 VALUES (ts0=20010101010101);
+INSERT INTO t1 VALUES (ts6=20010101010101);
+END;
+$$
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1(a INT)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
+BEGIN
+DECLARE i INT DEFAULT 123;
+DECLARE b8 BIT(8) DEFAULT 0x61;
+DECLARE t0 TIME DEFAULT '01:01:01';
+DECLARE t6 TIME(6) DEFAULT '01:01:01.123456';
+DECLARE d DATE DEFAULT '2001-01-01';
+DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01';
+DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456';
+DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01';
+DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456';
+INSERT INTO t1 VALUES (i=0x61);
+INSERT INTO t1 VALUES (b8=0x61);
+INSERT INTO t1 VALUES (t0=10101);
+INSERT INTO t1 VALUES (t6=10101);
+INSERT INTO t1 VALUES (d=20010101);
+INSERT INTO t1 VALUES (dt0=20010101010101);
+INSERT INTO t1 VALUES (dt6=20010101010101);
+INSERT INTO t1 VALUES (ts0=20010101010101);
+INSERT INTO t1 VALUES (ts6=20010101010101);
+END
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('i',123)=0x61)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('b8',_binary'a' COLLATE 'binary')=0x61)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('t0',TIME'01:01:01')=10101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('t6',TIME'01:01:01.123456')=10101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('d',DATE'2001-01-01')=20010101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('dt0',TIMESTAMP'2001-01-01 01:01:01')=20010101010101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('dt6',TIMESTAMP'2001-01-01 01:01:01.123456')=20010101010101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('ts0',TIMESTAMP'2001-01-01 01:01:01')=20010101010101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('ts6',TIMESTAMP'2001-01-01 01:01:01.123456')=20010101010101)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP PROCEDURE p1
diff --git a/mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result b/mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result
new file mode 100644
index 00000000000..cc21904f5af
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result
@@ -0,0 +1,227 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+CREATE TABLE t1 (a INT, b INT);
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+100 200
+10 1
+10 1
+10 20
+10 21
+11 NULL
+11 0
+11 NULL
+11 0
+12 NULL
+12 NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('rec.a',100), NAME_CONST('rec.b',200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,201))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,200)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,201)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE ROW(NULL,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(NULL,NULL)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(100,200)=ROW(NULL,NULL))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE ROW(NULL,NULL)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,NULL)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP PROCEDURE p1
+#
+# Testing ROW fields in LIMIT
+#
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+CREATE PROCEDURE p1()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+Warnings:
+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT)
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10),(10)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t2 (a INT)
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 1 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 2 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP TABLE "t1","t2" /* generated by server */
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP PROCEDURE p1
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
+#
+# MDEV-12291 Allow ROW variables as SELECT INTO targets
+#
+FLUSH LOGS;
+SET sql_mode=DEFAULT;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(32));
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 b10
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000003 # Binlog_checkpoint # # master-bin.000003
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT, b VARCHAR(32))
+master-bin.000003 # Gtid # # BEGIN GTID #-#-#
+master-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (10, 'b10')
+master-bin.000003 # Query # # COMMIT
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; CREATE TABLE t2 LIKE t1
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(32));
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END
+master-bin.000003 # Gtid # # BEGIN GTID #-#-#
+master-bin.000003 # Query # # use `test`; INSERT INTO t2 VALUES ( NAME_CONST('rec1.a',10), NAME_CONST('rec1.b',_latin1'b10' COLLATE 'latin1_swedish_ci'))
+master-bin.000003 # Query # # COMMIT
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; DROP TABLE `t2` /* generated by server */
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; DROP PROCEDURE p1
diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result
index 1cde61620a6..a2a5f434f18 100644
--- a/mysql-test/suite/binlog/r/binlog_unsafe.result
+++ b/mysql-test/suite/binlog/r/binlog_unsafe.result
@@ -85,8 +85,6 @@ DROP TRIGGER trig_2;
Invoking view view_retval_2 returning value from function func_retval_1 returning value from unsafe UUID() function.
CREATE VIEW view_retval_2 AS SELECT func_retval_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_retval_2;
Warnings:
@@ -149,8 +147,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking unsafe UUID() function.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -411,8 +407,6 @@ DROP TRIGGER trig_2;
Invoking view view_retval_2 returning value from function func_retval_1 returning value from unsafe @@hostname variable.
CREATE VIEW view_retval_2 AS SELECT func_retval_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_retval_2;
Warnings:
@@ -475,8 +469,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking unsafe @@hostname variable.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -657,8 +649,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking unsafe SELECT...LIMIT statement.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -1049,8 +1039,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking unsafe update of two autoinc columns.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -1245,8 +1233,6 @@ DROP TRIGGER trig_2;
Invoking view view_retval_2 returning value from function func_retval_1 returning value from unsafe UDF.
CREATE VIEW view_retval_2 AS SELECT func_retval_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_retval_2;
Warnings:
@@ -1309,8 +1295,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking unsafe UDF.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -1551,8 +1535,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking unsafe use of mysql.general_log.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses the general log, slow query log, or performance_schema table(s). This is unsafe because system tables may differ on slaves
* binlog_format = STATEMENT: expect 1 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -1823,14 +1805,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking statement that is unsafe in many ways.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses the general log, slow query log, or performance_schema table(s). This is unsafe because system tables may differ on slaves
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave
* binlog_format = STATEMENT: expect 7 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -2099,9 +2073,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking function func_sidef_1 invoking statement that is unsafe several times.
CREATE VIEW view_sidef_2 AS SELECT func_sidef_1();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
* binlog_format = STATEMENT: expect 2 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
@@ -2235,9 +2206,6 @@ DROP TRIGGER trig_1;
Invoking view view_sidef_1 invoking statement that is unsafe several times.
CREATE VIEW view_sidef_1 AS SELECT multi_unsafe_func();
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
* binlog_format = STATEMENT: expect 2 warnings.
INSERT INTO t1 SELECT * FROM view_sidef_1;
Warnings:
@@ -2281,9 +2249,6 @@ DROP TRIGGER trig_2;
Invoking view view_sidef_2 invoking view view_sidef_1 invoking statement that is unsafe several times.
CREATE VIEW view_sidef_2 AS SELECT * FROM view_sidef_1;
-Warnings:
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
-Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave
* binlog_format = STATEMENT: expect 2 warnings.
INSERT INTO t2 SELECT * FROM view_sidef_2;
Warnings:
diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp.test b/mysql-test/suite/binlog/t/binlog_stm_sp.test
new file mode 100644
index 00000000000..095b4c7f699
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_sp.test
@@ -0,0 +1,41 @@
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+--echo #
+--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly
+--echo #
+
+CREATE TABLE t1(a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE i INT DEFAULT 123;
+ DECLARE b8 BIT(8) DEFAULT 0x61;
+ DECLARE t0 TIME DEFAULT '01:01:01';
+ DECLARE t6 TIME(6) DEFAULT '01:01:01.123456';
+ DECLARE d DATE DEFAULT '2001-01-01';
+ DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01';
+ DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456';
+ DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01';
+ DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456';
+ INSERT INTO t1 VALUES (i=0x61);
+ INSERT INTO t1 VALUES (b8=0x61);
+ INSERT INTO t1 VALUES (t0=10101);
+ INSERT INTO t1 VALUES (t6=10101);
+ INSERT INTO t1 VALUES (d=20010101);
+ INSERT INTO t1 VALUES (dt0=20010101010101);
+ INSERT INTO t1 VALUES (dt6=20010101010101);
+ INSERT INTO t1 VALUES (ts0=20010101010101);
+ INSERT INTO t1 VALUES (ts6=20010101010101);
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test
new file mode 100644
index 00000000000..a7e21ee55c5
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test
@@ -0,0 +1,108 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:=100;
+ rec.b:=200;
+ INSERT INTO t1 VALUES (rec.a,rec.b);
+ INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.a:=NULL;
+ INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+ INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+ INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+ INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.b:=NULL;
+ INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # Testing ROW fields in LIMIT
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT:= 1;
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 1;
+ INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+ INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+--echo #
+--echo # MDEV-12291 Allow ROW variables as SELECT INTO targets
+--echo #
+
+FLUSH LOGS;
+SET sql_mode=DEFAULT;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(32));
+ SELECT * INTO rec1 FROM t1;
+ INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result b/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result
new file mode 100644
index 00000000000..c60e3493b3f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result
@@ -0,0 +1,67 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10801 sql_mode: dynamic SQL placeholders
+#
+CREATE TABLE t1 (a INT, b INT);
+SET @a=10, @b=20;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (?,?)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:a,:b)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:aaa,:bbb)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"a",:"b")';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"aaa",:"bbb")';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:1,:2)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:222,:111)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:0,:65535)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:65535,:0)';
+EXECUTE stmt USING @a, @b;
+SELECT * FROM t1;
+a b
+10 20
+10 20
+10 20
+10 20
+10 20
+10 20
+10 20
+10 20
+10 20
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20)
+master-bin.000001 # Query # # COMMIT
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/binlog_stm_sp.result b/mysql-test/suite/compat/oracle/r/binlog_stm_sp.result
new file mode 100644
index 00000000000..9823b155c8f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/binlog_stm_sp.result
@@ -0,0 +1,477 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+CREATE TABLE t1 (a INT, b INT);
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+100 200
+10 1
+10 1
+10 20
+10 21
+11 NULL
+11 0
+11 NULL
+11 0
+12 NULL
+12 NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('rec.a',100), NAME_CONST('rec.b',200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,201))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,200)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,201)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE ROW(NULL,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(NULL,NULL)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(100,200)=ROW(NULL,NULL))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE ROW(NULL,NULL)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,NULL)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP PROCEDURE p1
+#
+# Testing ROW fields in LIMIT
+#
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+CREATE PROCEDURE p1()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+Warnings:
+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT)
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10),(10)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t2 (a INT)
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 1 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 2 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP TABLE "t1","t2" /* generated by server */
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP PROCEDURE p1
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
+#
+# MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
+#
+CREATE TABLE t1 (a INT, b INT);
+CREATE PROCEDURE p1
+AS
+rec t1%ROWTYPE;
+BEGIN
+rec.a:=100;
+rec.b:=200;
+SELECT rec=ROW(100,200) AS true1, ROW(100,200)=rec AS true2;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+CALL p1();
+true1 true2
+1 1
+SELECT * FROM t1;
+a b
+100 200
+10 1
+10 1
+10 20
+10 21
+11 NULL
+11 0
+11 NULL
+11 0
+12 NULL
+12 NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT)
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10),(10)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t2 (a INT)
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 1 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 2 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP TABLE "t1","t2" /* generated by server */
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP PROCEDURE p1
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec t1%ROWTYPE;
+BEGIN
+rec.a:=100;
+rec.b:=200;
+SELECT rec=ROW(100,200) AS true1, ROW(100,200)=rec AS true2;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('rec.a',100), NAME_CONST('rec.b',200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,201))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,200)=ROW(NULL,200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,201)=ROW(NULL,200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE ROW(NULL,200)=ROW(100,200)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,200)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(NULL,NULL)=ROW(100,200))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(100,200)=ROW(NULL,NULL))
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE ROW(NULL,NULL)=ROW(100,200)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,NULL)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP PROCEDURE p1
+#
+# MDEV-12291 Allow ROW variables as SELECT INTO targets
+#
+FLUSH LOGS;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 b10
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000003 # Binlog_checkpoint # # master-bin.000003
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; CREATE TABLE t1 (a INT, b VARCHAR(32))
+master-bin.000003 # Gtid # # BEGIN GTID #-#-#
+master-bin.000003 # Query # # use `test`; INSERT INTO t1 VALUES (10, 'b10')
+master-bin.000003 # Query # # COMMIT
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; CREATE TABLE t2 LIKE t1
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END
+master-bin.000003 # Gtid # # BEGIN GTID #-#-#
+master-bin.000003 # Query # # use `test`; INSERT INTO t2 VALUES ( NAME_CONST('rec1.a',10), NAME_CONST('rec1.b',_latin1'b10' COLLATE 'latin1_swedish_ci'))
+master-bin.000003 # Query # # COMMIT
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; DROP TABLE "t2" /* generated by server */
+master-bin.000003 # Gtid # # GTID #-#-#
+master-bin.000003 # Query # # use `test`; DROP PROCEDURE p1
+FLUSH LOGS;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+CREATE PROCEDURE p1
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 b10
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000004 # Binlog_checkpoint # # master-bin.000004
+master-bin.000004 # Gtid # # GTID #-#-#
+master-bin.000004 # Query # # use `test`; CREATE TABLE t1 (a INT, b VARCHAR(32))
+master-bin.000004 # Gtid # # BEGIN GTID #-#-#
+master-bin.000004 # Query # # use `test`; INSERT INTO t1 VALUES (10, 'b10')
+master-bin.000004 # Query # # COMMIT
+master-bin.000004 # Gtid # # GTID #-#-#
+master-bin.000004 # Query # # use `test`; CREATE TABLE t2 LIKE t1
+master-bin.000004 # Gtid # # GTID #-#-#
+master-bin.000004 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END
+master-bin.000004 # Gtid # # BEGIN GTID #-#-#
+master-bin.000004 # Query # # use `test`; INSERT INTO t2 VALUES ( NAME_CONST('rec1.a',10), NAME_CONST('rec1.b',_latin1'b10' COLLATE 'latin1_swedish_ci'))
+master-bin.000004 # Query # # COMMIT
+master-bin.000004 # Gtid # # GTID #-#-#
+master-bin.000004 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000004 # Gtid # # GTID #-#-#
+master-bin.000004 # Query # # use `test`; DROP TABLE "t2" /* generated by server */
+master-bin.000004 # Gtid # # GTID #-#-#
+master-bin.000004 # Query # # use `test`; DROP PROCEDURE p1
+FLUSH LOGS;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+CREATE PROCEDURE p1
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+rec1 cur1%ROWTYPE;
+BEGIN
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 b10
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000005 # Binlog_checkpoint # # master-bin.000005
+master-bin.000005 # Gtid # # GTID #-#-#
+master-bin.000005 # Query # # use `test`; CREATE TABLE t1 (a INT, b VARCHAR(32))
+master-bin.000005 # Gtid # # BEGIN GTID #-#-#
+master-bin.000005 # Query # # use `test`; INSERT INTO t1 VALUES (10, 'b10')
+master-bin.000005 # Query # # COMMIT
+master-bin.000005 # Gtid # # GTID #-#-#
+master-bin.000005 # Query # # use `test`; CREATE TABLE t2 LIKE t1
+master-bin.000005 # Gtid # # GTID #-#-#
+master-bin.000005 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+rec1 cur1%ROWTYPE;
+BEGIN
+SELECT * INTO rec1 FROM t1;
+INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END
+master-bin.000005 # Gtid # # BEGIN GTID #-#-#
+master-bin.000005 # Query # # use `test`; INSERT INTO t2 VALUES ( NAME_CONST('rec1.a',10), NAME_CONST('rec1.b',_latin1'b10' COLLATE 'latin1_swedish_ci'))
+master-bin.000005 # Query # # COMMIT
+master-bin.000005 # Gtid # # GTID #-#-#
+master-bin.000005 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000005 # Gtid # # GTID #-#-#
+master-bin.000005 # Query # # use `test`; DROP TABLE "t2" /* generated by server */
+master-bin.000005 # Gtid # # GTID #-#-#
+master-bin.000005 # Query # # use `test`; DROP PROCEDURE p1
diff --git a/mysql-test/suite/compat/oracle/r/exception.result b/mysql-test/suite/compat/oracle/r/exception.result
new file mode 100644
index 00000000000..b61d25f36ee
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/exception.result
@@ -0,0 +1,409 @@
+SET sql_mode=ORACLE;
+#
+# sql_mode=ORACLE: Predefined exceptions: TOO_MANY_ROWS, NO_DATA_FOUND, DUP_VAL_ON_INDEX
+#
+#
+# Testing NO_DATA_FOUND and TOO_MANY_ROWS
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1 LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN res:='--- too_many_rows cought ---';
+WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought ---';
+END;
+$$
+SET @res='';
+CALL p1(0, @res);
+SELECT @res;
+@res
+--- no_data_found cought ---
+CALL p1(2, @res);
+SELECT @res;
+@res
+--- too_many_rows cought ---
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing DUP_VAL_ON_INDEX
+#
+CREATE TABLE t1 (a INT PRIMARY KEY);
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+BEGIN
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (10);
+EXCEPTION
+WHEN DUP_VAL_ON_INDEX THEN res:='--- dup_val_on_index cought ---';
+END;
+$$
+SET @res='';
+CALL p1(@res);
+SELECT @res;
+@res
+--- dup_val_on_index cought ---
+SELECT * FROM t1;
+a
+10
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions
+#
+#
+# RAISE outside of an SP context
+#
+RAISE NO_DATA_FOUND;
+ERROR 42000: Undefined CONDITION: NO_DATA_FOUND
+RAISE INVALID_CURSOR;
+ERROR 42000: Undefined CONDITION: INVALID_CURSOR
+RAISE DUP_VAL_ON_INDEX;
+ERROR 42000: Undefined CONDITION: DUP_VAL_ON_INDEX
+RAISE TOO_MANY_ROWS;
+ERROR 42000: Undefined CONDITION: TOO_MANY_ROWS
+RAISE;
+ERROR 0K000: RESIGNAL when handler not active
+#
+# RAISE for an undefinite exception
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+RAISE xxx;
+END;
+$$
+ERROR 42000: Undefined CONDITION: xxx
+#
+# RAISE for predefined exceptions
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+RAISE no_data_found;
+END;
+$$
+CALL p1();
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+RAISE invalid_cursor;
+END;
+$$
+CALL p1();
+ERROR 24000: Cursor is not open
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+RAISE dup_val_on_index;
+END;
+$$
+CALL p1();
+ERROR 23000: Duplicate entry '%-.192s' for key %d
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+raise too_many_rows;
+END;
+$$
+CALL p1();
+ERROR 42000: Result consisted of more than one row
+DROP PROCEDURE p1;
+#
+# RAISE with no exception name (resignal)
+#
+CREATE PROCEDURE p1()
+AS
+BEGIN
+RAISE;
+END;
+$$
+CALL p1();
+ERROR 0K000: RESIGNAL when handler not active
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1(lim INT)
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1 LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN RAISE;
+WHEN NO_DATA_FOUND THEN RAISE;
+END;
+$$
+CALL p1(0);
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+CALL p1(2);
+ERROR 42000: Result consisted of more than one row
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1(lim INT)
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1 LIMIT lim;
+EXCEPTION
+WHEN OTHERS THEN RAISE;
+END;
+$$
+CALL p1(0);
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+CALL p1(2);
+ERROR 42000: Result consisted of more than one row
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+a INT;
+CURSOR c IS SELECT a FROM t1;
+BEGIN
+FETCH c INTO a;
+EXCEPTION
+WHEN INVALID_CURSOR THEN RAISE;
+END;
+$$
+CALL p1();
+ERROR 24000: Cursor is not open
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+a INT;
+CURSOR c IS SELECT a FROM t1;
+BEGIN
+FETCH c INTO a;
+EXCEPTION
+WHEN OTHERS THEN RAISE;
+END;
+$$
+CALL p1();
+ERROR 24000: Cursor is not open
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that warning-alike errors are caught by OTHERS
+#
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+a INT:=10;
+BEGIN
+SELECT a INTO a FROM t1;
+RETURN 'OK';
+EXCEPTION
+WHEN OTHERS THEN RETURN 'Exception';
+END;
+$$
+SELECT f1() FROM DUAL;
+f1()
+Exception
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# End of MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions
+#
+#
+# MDEV-10587 sql_mode=ORACLE: User defined exceptions
+#
+#
+# Checking that duplicate WHEN clause is not allowed
+#
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+e EXCEPTION;
+BEGIN
+RETURN 'Got no exceptions';
+EXCEPTION
+WHEN e THEN RETURN 'Got exception e';
+WHEN e THEN RETURN 'Got exception e';
+END;
+$$
+ERROR 42000: Duplicate handler declared in the same block
+#
+# Checking that raised user exceptions are further caught by name
+#
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+e EXCEPTION;
+f EXCEPTION;
+BEGIN
+IF c = 'e' THEN RAISE e; END IF;
+IF c = 'f' THEN RAISE f; END IF;
+RETURN 'Got no exceptions';
+EXCEPTION
+WHEN e THEN RETURN 'Got exception e';
+END;
+$$
+SELECT f1('');
+f1('')
+Got no exceptions
+SELECT f1('e');
+f1('e')
+Got exception e
+SELECT f1('f');
+ERROR 45000: Unhandled user-defined exception condition
+DROP FUNCTION f1;
+#
+# Checking that raised user exceptions are further caught by OTHERS
+#
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+e EXCEPTION;
+f EXCEPTION;
+BEGIN
+IF c = 'e' THEN RAISE e; END IF;
+IF c = 'f' THEN RAISE f; END IF;
+RETURN 'Got no exceptions';
+EXCEPTION
+WHEN OTHERS THEN RETURN 'Got some exception';
+END;
+$$
+SELECT f1('');
+f1('')
+Got no exceptions
+SELECT f1('e');
+f1('e')
+Got some exception
+SELECT f1('f');
+f1('f')
+Got some exception
+DROP FUNCTION f1;
+#
+# Checking that 'WHEN e .. WHEN f' does not produce ER_SP_DUP_HANDLER
+#
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+e EXCEPTION;
+f EXCEPTION;
+a VARCHAR(64):='';
+BEGIN
+BEGIN
+IF c = 'e' THEN RAISE e; END IF;
+IF c = 'f' THEN RAISE f; END IF;
+EXCEPTION
+WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE e; END;
+WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE f; END;
+END;
+RETURN 'Got no exceptions';
+EXCEPTION
+WHEN OTHERS THEN RETURN a || 'Got EXCEPTION2/OTHERS;';
+END;
+$$
+SELECT f1('');
+f1('')
+Got no exceptions
+SELECT f1('e');
+f1('e')
+Got EXCEPTION1/e; Got EXCEPTION2/OTHERS;
+SELECT f1('f');
+f1('f')
+Got EXCEPTION1/f; Got EXCEPTION2/OTHERS;
+DROP FUNCTION f1;
+#
+# Checking that resignaled user exceptions are further caught by name
+#
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+e EXCEPTION;
+f EXCEPTION;
+a VARCHAR(64):='';
+BEGIN
+BEGIN
+IF c = 'e' THEN RAISE e; END IF;
+IF c = 'f' THEN RAISE f; END IF;
+EXCEPTION
+WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE; END;
+WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE; END;
+END;
+RETURN 'Got no exceptions';
+EXCEPTION
+WHEN e THEN RETURN a || 'Got EXCEPTION2/e;';
+END;
+$$
+SELECT f1('');
+f1('')
+Got no exceptions
+SELECT f1('e');
+f1('e')
+Got EXCEPTION1/e; Got EXCEPTION2/e;
+SELECT f1('f');
+ERROR 45000: Unhandled user-defined exception condition
+DROP FUNCTION f1;
+#
+# Checking that resignaled user exceptions are further caught by OTHERS
+#
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+e EXCEPTION;
+f EXCEPTION;
+a VARCHAR(64):='';
+BEGIN
+BEGIN
+IF c = 'e' THEN RAISE e; END IF;
+IF c = 'f' THEN RAISE f; END IF;
+EXCEPTION
+WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE; END;
+WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE; END;
+END;
+RETURN 'Got no exceptions';
+EXCEPTION
+WHEN OTHERS THEN RETURN a || 'Got EXCEPTION2/OTHERS;';
+END;
+$$
+SELECT f1('');
+f1('')
+Got no exceptions
+SELECT f1('e');
+f1('e')
+Got EXCEPTION1/e; Got EXCEPTION2/OTHERS;
+SELECT f1('f');
+f1('f')
+Got EXCEPTION1/f; Got EXCEPTION2/OTHERS;
+DROP FUNCTION f1;
+#
+# End of MDEV-10587 sql_mode=ORACLE: User defined exceptions
+#
+#
+# MDEV-12088 sql_mode=ORACLE: Do not require BEGIN..END in multi-statement exception handlers in THEN clause
+#
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (10),(20),(30);
+CREATE PROCEDURE p1(a INT) AS
+BEGIN
+INSERT INTO t1 (a) VALUES (a);
+EXCEPTION
+WHEN DUP_VAL_ON_INDEX THEN
+a:= a+1;
+INSERT INTO t1 VALUES (a);
+WHEN OTHERS THEN
+NULL;
+NULL;
+END;
+$$
+CALL p1(30);
+SELECT * FROM t1;
+a
+10
+20
+30
+31
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/func_case.result b/mysql-test/suite/compat/oracle/r/func_case.result
new file mode 100644
index 00000000000..dfe2d165b88
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/func_case.result
@@ -0,0 +1,7 @@
+SET sql_mode=ORACLE;
+SELECT NVL(NULL, 'a'), NVL('a', 'b');
+NVL(NULL, 'a') NVL('a', 'b')
+a a
+SELECT NVL2(NULL, 'a', 'b'), NVL2('a', 'b', 'c');
+NVL2(NULL, 'a', 'b') NVL2('a', 'b', 'c')
+b b
diff --git a/mysql-test/suite/compat/oracle/r/func_concat.result b/mysql-test/suite/compat/oracle/r/func_concat.result
new file mode 100644
index 00000000000..230b36b94a5
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/func_concat.result
@@ -0,0 +1,257 @@
+SET sql_mode=ORACLE;
+EXPLAIN EXTENDED SELECT 'a'||'b'||'c';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select concat_operator_oracle(concat_operator_oracle('a','b'),'c') AS "'a'||'b'||'c'"
+EXPLAIN EXTENDED SELECT CONCAT('a'||'b'||'c');
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select concat_operator_oracle(concat_operator_oracle(concat_operator_oracle('a','b'),'c')) AS "CONCAT('a'||'b'||'c')"
+SELECT '' || '';
+'' || ''
+
+SELECT '' || 'b';
+'' || 'b'
+b
+SELECT '' || NULL;
+'' || NULL
+
+SELECT 'a' || '';
+'a' || ''
+a
+SELECT 'a' || 'b';
+'a' || 'b'
+ab
+SELECT 'a' || NULL;
+'a' || NULL
+a
+SELECT NULL || '';
+NULL || ''
+
+SELECT NULL || 'b';
+NULL || 'b'
+b
+SELECT NULL || NULL;
+NULL || NULL
+NULL
+SELECT '' || '' || '';
+'' || '' || ''
+
+SELECT '' || '' || 'c';
+'' || '' || 'c'
+c
+SELECT '' || '' || NULL;
+'' || '' || NULL
+
+SELECT '' || 'b' || '';
+'' || 'b' || ''
+b
+SELECT '' || 'b' || 'c';
+'' || 'b' || 'c'
+bc
+SELECT '' || 'b' || NULL;
+'' || 'b' || NULL
+b
+SELECT '' || NULL || '';
+'' || NULL || ''
+
+SELECT '' || NULL || 'c';
+'' || NULL || 'c'
+c
+SELECT '' || NULL || NULL;
+'' || NULL || NULL
+
+SELECT 'a' || '' || '';
+'a' || '' || ''
+a
+SELECT 'a' || '' || 'c';
+'a' || '' || 'c'
+ac
+SELECT 'a' || '' || NULL;
+'a' || '' || NULL
+a
+SELECT 'a' || 'b' || '';
+'a' || 'b' || ''
+ab
+SELECT 'a' || 'b' || 'c';
+'a' || 'b' || 'c'
+abc
+SELECT 'a' || 'b' || NULL;
+'a' || 'b' || NULL
+ab
+SELECT 'a' || NULL || '';
+'a' || NULL || ''
+a
+SELECT 'a' || NULL || 'c';
+'a' || NULL || 'c'
+ac
+SELECT 'a' || NULL || NULL;
+'a' || NULL || NULL
+a
+SELECT NULL || '' || '';
+NULL || '' || ''
+
+SELECT NULL || '' || 'c';
+NULL || '' || 'c'
+c
+SELECT NULL || '' || NULL;
+NULL || '' || NULL
+
+SELECT NULL || 'b' || '';
+NULL || 'b' || ''
+b
+SELECT NULL || 'b' || 'c';
+NULL || 'b' || 'c'
+bc
+SELECT NULL || 'b' || NULL;
+NULL || 'b' || NULL
+b
+SELECT NULL || NULL || '';
+NULL || NULL || ''
+
+SELECT NULL || NULL || 'c';
+NULL || NULL || 'c'
+c
+SELECT NULL || NULL || NULL;
+NULL || NULL || NULL
+NULL
+CREATE TABLE t1 (a VARCHAR(10), b VARCHAR(10), c VARCHAR(10));
+INSERT INTO t1 VALUES ('', '', '');
+INSERT INTO t1 VALUES ('', '', 'c');
+INSERT INTO t1 VALUES ('', '', NULL);
+INSERT INTO t1 VALUES ('', 'b', '');
+INSERT INTO t1 VALUES ('', 'b', 'c');
+INSERT INTO t1 VALUES ('', 'b', NULL);
+INSERT INTO t1 VALUES ('', NULL, '');
+INSERT INTO t1 VALUES ('', NULL, 'c');
+INSERT INTO t1 VALUES ('', NULL, NULL);
+INSERT INTO t1 VALUES ('a', '', '');
+INSERT INTO t1 VALUES ('a', '', 'c');
+INSERT INTO t1 VALUES ('a', '', NULL);
+INSERT INTO t1 VALUES ('a', 'b', '');
+INSERT INTO t1 VALUES ('a', 'b', 'c');
+INSERT INTO t1 VALUES ('a', 'b', NULL);
+INSERT INTO t1 VALUES ('a', NULL, '');
+INSERT INTO t1 VALUES ('a', NULL, 'c');
+INSERT INTO t1 VALUES ('a', NULL, NULL);
+INSERT INTO t1 VALUES (NULL, '', '');
+INSERT INTO t1 VALUES (NULL, '', 'c');
+INSERT INTO t1 VALUES (NULL, '', NULL);
+INSERT INTO t1 VALUES (NULL, 'b', '');
+INSERT INTO t1 VALUES (NULL, 'b', 'c');
+INSERT INTO t1 VALUES (NULL, 'b', NULL);
+INSERT INTO t1 VALUES (NULL, NULL, '');
+INSERT INTO t1 VALUES (NULL, NULL, 'c');
+INSERT INTO t1 VALUES (NULL, NULL, NULL);
+SELECT LENGTH(a||b||c), a||b||c FROM t1 ORDER BY a,b,c;
+LENGTH(a||b||c) a||b||c
+NULL NULL
+0
+1 c
+0
+0
+1 c
+1 b
+1 b
+2 bc
+0
+0
+1 c
+0
+0
+1 c
+1 b
+1 b
+2 bc
+1 a
+1 a
+2 ac
+1 a
+1 a
+2 ac
+2 ab
+2 ab
+3 abc
+SELECT LENGTH(CONCAT(a||b||c)), CONCAT(a||b||c) FROM t1 ORDER BY a,b,c;
+LENGTH(CONCAT(a||b||c)) CONCAT(a||b||c)
+NULL NULL
+0
+1 c
+0
+0
+1 c
+1 b
+1 b
+2 bc
+0
+0
+1 c
+0
+0
+1 c
+1 b
+1 b
+2 bc
+1 a
+1 a
+2 ac
+1 a
+1 a
+2 ac
+2 ab
+2 ab
+3 abc
+DROP TABLE t1;
+#
+# MDEV-12478 CONCAT function inside view casts values incorrectly with Oracle sql_mode
+#
+SET sql_mode=ORACLE;
+CREATE VIEW v1 AS SELECT 'foo'||NULL||'bar' AS test;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE VIEW "v1" AS select concat_operator_oracle(concat_operator_oracle('foo',NULL),'bar') AS "test" latin1 latin1_swedish_ci
+SELECT * FROM v1;
+test
+foobar
+SET sql_mode=DEFAULT;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select concat_operator_oracle(concat_operator_oracle('foo',NULL),'bar') AS `test` latin1 latin1_swedish_ci
+SELECT * FROM v1;
+test
+foobar
+DROP VIEW v1;
+SET sql_mode=DEFAULT;
+CREATE VIEW v1 AS SELECT CONCAT('foo',NULL,'bar') AS test;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select concat('foo',NULL,'bar') AS `test` latin1 latin1_swedish_ci
+SELECT * FROM v1;
+test
+NULL
+SET sql_mode=ORACLE;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE VIEW "v1" AS select concat('foo',NULL,'bar') AS "test" latin1 latin1_swedish_ci
+SELECT * FROM v1;
+test
+NULL
+DROP VIEW v1;
+SET sql_mode=DEFAULT;
+CREATE VIEW v1 AS SELECT '0'||'1' AS test;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select '0' or '1' AS `test` latin1 latin1_swedish_ci
+SELECT * FROM v1;
+test
+1
+SET sql_mode=ORACLE;
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE VIEW "v1" AS select '0' or '1' AS "test" latin1 latin1_swedish_ci
+SELECT * FROM v1;
+test
+1
+DROP VIEW v1;
diff --git a/mysql-test/suite/compat/oracle/r/func_decode.result b/mysql-test/suite/compat/oracle/r/func_decode.result
new file mode 100644
index 00000000000..c4bfb713e61
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/func_decode.result
@@ -0,0 +1,33 @@
+SET sql_mode=ORACLE;
+SELECT DECODE(10);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
+SELECT DECODE(10,10);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1
+SELECT DECODE(10,10,'x10');
+DECODE(10,10,'x10')
+x10
+SELECT DECODE(11,10,'x10');
+DECODE(11,10,'x10')
+NULL
+SELECT DECODE(10,10,'x10','def');
+DECODE(10,10,'x10','def')
+x10
+SELECT DECODE(11,10,'x10','def');
+DECODE(11,10,'x10','def')
+def
+SELECT DECODE(10,10,'x10',11,'x11','def');
+DECODE(10,10,'x10',11,'x11','def')
+x10
+SELECT DECODE(11,10,'x10',11,'x11','def');
+DECODE(11,10,'x10',11,'x11','def')
+x11
+SELECT DECODE(12,10,'x10',11,'x11','def');
+DECODE(12,10,'x10',11,'x11','def')
+def
+EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select case 12 when 10 then 'x10' when 11 then 'x11' else 'def' end AS "DECODE(12,10,'x10',11,'x11','def')"
+CREATE TABLE decode (decode int);
+DROP TABLE decode;
diff --git a/mysql-test/suite/compat/oracle/r/func_length.result b/mysql-test/suite/compat/oracle/r/func_length.result
new file mode 100644
index 00000000000..e260f5ad6da
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/func_length.result
@@ -0,0 +1,21 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-12783 sql_mode=ORACLE: Functions LENGTH() and LENGTHB()
+#
+SELECT LENGTH(null), LENGTH('a'), LENGTH(123);
+LENGTH(null) LENGTH('a') LENGTH(123)
+NULL 1 3
+SELECT LENGTHB(null), LENGTHB('a'), LENGTHB(123);
+LENGTHB(null) LENGTHB('a') LENGTHB(123)
+NULL 1 3
+SELECT LENGTH(_utf8 0xC39F), LENGTH(CHAR(14844588 USING utf8));
+LENGTH(_utf8 0xC39F) LENGTH(CHAR(14844588 USING utf8))
+1 1
+SELECT LENGTHB(_utf8 0xC39F), LENGTHB(CHAR(14844588 USING utf8));
+LENGTHB(_utf8 0xC39F) LENGTHB(CHAR(14844588 USING utf8))
+2 3
+EXPLAIN EXTENDED SELECT LENGTH('a'), LENGTHB('a');
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select char_length('a') AS "LENGTH('a')",octet_length('a') AS "LENGTHB('a')"
diff --git a/mysql-test/suite/compat/oracle/r/func_misc.result b/mysql-test/suite/compat/oracle/r/func_misc.result
new file mode 100644
index 00000000000..0e2ba0c6f50
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/func_misc.result
@@ -0,0 +1,319 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
+#
+#
+# Using SQLCODE and SQLERRM outside of an SP
+#
+SELECT SQLCODE;
+ERROR 42S22: Unknown column 'SQLCODE' in 'field list'
+SELECT SQLERRM;
+ERROR 42S22: Unknown column 'SQLERRM' in 'field list'
+CREATE TABLE t1 (SQLCODE INT, SQLERRM VARCHAR(10));
+INSERT INTO t1 VALUES (10, 'test');
+SELECT SQLCODE, SQLERRM FROM t1;
+SQLCODE SQLERRM
+10 test
+DROP TABLE t1;
+#
+# Normal SQLCODE and SQLERRM usage
+#
+CREATE PROCEDURE p1(stmt VARCHAR)
+AS
+BEGIN
+EXECUTE IMMEDIATE stmt;
+SELECT 'Error1: ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+WHEN OTHERS THEN
+SELECT 'Error2: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CALL p1('SELECT 1');
+1
+1
+'Error1: ' || SQLCODE || ' ' || SQLERRM
+Error1: 0 normal, successful completition
+CALL p1('xxx');
+'Error2: ' || SQLCODE || ' ' || SQLERRM
+Error2: 1193 Unknown system variable 'xxx'
+CALL p1('SELECT 1');
+1
+1
+'Error1: ' || SQLCODE || ' ' || SQLERRM
+Error1: 0 normal, successful completition
+DROP PROCEDURE p1;
+#
+# SQLCODE and SQLERRM hidden by local variables
+#
+CREATE PROCEDURE p1()
+AS
+sqlcode INT:= 10;
+sqlerrm VARCHAR(64) := 'test';
+BEGIN
+SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CALL p1;
+'Error: ' || SQLCODE || ' ' || SQLERRM
+Error: 10 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+sqlcode INT;
+sqlerrm VARCHAR(64);
+BEGIN
+SQLCODE:= 10;
+sqlerrm:= 'test';
+SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CALL p1;
+'Error: ' || SQLCODE || ' ' || SQLERRM
+Error: 10 test
+DROP PROCEDURE p1;
+#
+# SQLCODE and SQLERRM hidden by parameters
+#
+CREATE PROCEDURE p1(sqlcode INT, sqlerrm VARCHAR)
+AS
+BEGIN
+SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CALL p1(10, 'test');
+'Error: ' || SQLCODE || ' ' || SQLERRM
+Error: 10 test
+DROP PROCEDURE p1;
+#
+# SQLCODE and SQLERRM in CREATE..SELECT
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+CREATE TABLE t1 AS SELECT SQLCODE, SQLERRM;
+END;
+$$
+CALL p1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "SQLCODE" int(11) NOT NULL,
+ "SQLERRM" varchar(512) CHARACTER SET utf8 NOT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SQLCODE and SQLERRM in EXPLAIN EXTENDED SELECT
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+EXPLAIN EXTENDED SELECT SQLCode, SQLErrm;
+END;
+$$
+CALL p1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select SQLCODE AS "SQLCode",SQLERRM AS "SQLErrm"
+DROP PROCEDURE p1;
+#
+# Warning-alike errors in stored functions
+#
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1;
+RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+WHEN NO_DATA_FOUND THEN
+RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+SELECT f1() FROM DUAL;
+f1()
+Exception 1329 No data - zero rows fetched, selected, or processed
+DROP FUNCTION f1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1;
+RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+WHEN OTHERS THEN
+RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+SELECT f1() FROM DUAL;
+f1()
+Exception 1329 No data - zero rows fetched, selected, or processed
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Warning-alike errors in stored procedures
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1;
+res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+WHEN NO_DATA_FOUND THEN
+res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CALL p1(@a);
+SELECT @a;
+@a
+Exception 1329 No data - zero rows fetched, selected, or processed
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+SELECT a INTO a FROM t1;
+res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+WHEN OTHERS THEN
+res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CALL p1(@a);
+SELECT @a;
+@a
+Exception 1329 No data - zero rows fetched, selected, or processed
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# SQLCODE and SQLERRM are cleared on RETURN
+#
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+a INT:=10;
+BEGIN
+SELECT a INTO a FROM t1;
+RETURN 'Value=' || a;
+EXCEPTION
+WHEN NO_DATA_FOUND THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+a VARCHAR(128);
+BEGIN
+RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+SELECT f1() FROM DUAL;
+f1()
+Exception|1329 No data - zero rows fetched, selected, or processed
+SELECT f2() FROM DUAL;
+f2()
+Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
+DROP TABLE t1;
+DROP FUNCTION f2;
+DROP FUNCTION f1;
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+a INT:=10;
+BEGIN
+SELECT a INTO a FROM t1;
+RETURN 'Value=' || a;
+EXCEPTION
+WHEN OTHERS THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+a VARCHAR(128);
+BEGIN
+RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+SELECT f1() FROM DUAL;
+f1()
+Exception|1329 No data - zero rows fetched, selected, or processed
+SELECT f2() FROM DUAL;
+f2()
+Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
+DROP TABLE t1;
+DROP FUNCTION f2;
+DROP FUNCTION f1;
+#
+# SQLCODE and SQLERRM are cleared on a return from a PROCEDURE
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+a INT:=10;
+BEGIN
+SELECT a INTO a FROM t1;
+res:='Value=' || a;
+EXCEPTION
+WHEN NO_DATA_FOUND THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+res VARCHAR(128);
+BEGIN
+CALL p1(res);
+RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+SELECT f2() FROM DUAL;
+f2()
+Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
+DROP FUNCTION f2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+a INT:=10;
+BEGIN
+SELECT a INTO a FROM t1;
+res:='Value=' || a;
+EXCEPTION
+WHEN OTHERS THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+res VARCHAR(128);
+BEGIN
+CALL p1(res);
+RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+SELECT f2() FROM DUAL;
+f2()
+Exception|1329 No data - zero rows fetched, selected, or processed|0 normal, successful completition
+DROP FUNCTION f2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# End of MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
+#
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+BEGIN
+SELECT SQLCODE;
+END
+$$
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def SQLCODE 3 11 1 N 32897 0 63
+SQLCODE
+0
diff --git a/mysql-test/suite/compat/oracle/r/misc.result b/mysql-test/suite/compat/oracle/r/misc.result
new file mode 100644
index 00000000000..38f38bd07e6
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/misc.result
@@ -0,0 +1,12 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-12086 sql_mode=ORACLE: allow SELECT UNIQUE as a synonym for SELECT DISTINCT
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20),(20),(30),(30),(30);
+SELECT UNIQUE a FROM t1;
+a
+10
+20
+30
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/ps.result b/mysql-test/suite/compat/oracle/r/ps.result
new file mode 100644
index 00000000000..ed7cb4c51d5
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/ps.result
@@ -0,0 +1,249 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10801 sql_mode: dynamic SQL placeholders
+#
+SET @a=10, @b=20;
+PREPARE stmt FROM 'SELECT ?,?';
+EXECUTE stmt USING @a, @b;
+? ?
+10 20
+PREPARE stmt FROM 'SELECT :a,:b';
+EXECUTE stmt USING @a, @b;
+:a :b
+10 20
+PREPARE stmt FROM 'SELECT :aaa,:bbb';
+EXECUTE stmt USING @a, @b;
+:aaa :bbb
+10 20
+PREPARE stmt FROM 'SELECT :"a",:"b"';
+EXECUTE stmt USING @a, @b;
+:"a" :"b"
+10 20
+PREPARE stmt FROM 'SELECT :"aaa",:"bbb"';
+EXECUTE stmt USING @a, @b;
+:"aaa" :"bbb"
+10 20
+PREPARE stmt FROM 'SELECT :1,:2';
+EXECUTE stmt USING @a, @b;
+:1 :2
+10 20
+PREPARE stmt FROM 'SELECT :222,:111';
+EXECUTE stmt USING @a, @b;
+:222 :111
+10 20
+PREPARE stmt FROM 'SELECT :0,:65535';
+EXECUTE stmt USING @a, @b;
+:0 :65535
+10 20
+PREPARE stmt FROM 'SELECT :65535,:0';
+EXECUTE stmt USING @a, @b;
+:65535 :0
+10 20
+#
+# MDEV-10709 Expressions as parameters to Dynamic SQL
+#
+#
+# Testing disallowed expressions in USING
+#
+PREPARE stmt FROM 'SELECT :1 FROM DUAL';
+EXECUTE stmt USING (SELECT 1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+DEALLOCATE PREPARE stmt;
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+BEGIN
+RETURN 'test';
+END;
+$$
+PREPARE stmt FROM 'SELECT ? FROM DUAL';
+EXECUTE stmt USING f1();
+ERROR 42000: EXECUTE..USING does not support subqueries or stored functions
+DEALLOCATE PREPARE stmt;
+DROP FUNCTION f1;
+#
+# Using a user variable as a EXECUTE..USING out parameter
+#
+CREATE PROCEDURE p1(a OUT INT)
+AS
+BEGIN
+a:= 10;
+END;
+/
+SET @a=1;
+CALL p1(@a);
+SELECT @a;
+@a
+10
+SET @a=2;
+PREPARE stmt FROM 'CALL p1(?)';
+EXECUTE stmt USING @a;
+SELECT @a;
+@a
+10
+DROP PROCEDURE p1;
+#
+# Using an SP variable as a EXECUTE..USING out parameter
+#
+CREATE PROCEDURE p1 (a OUT INT)
+AS
+BEGIN
+a:=10;
+END;
+/
+CREATE PROCEDURE p2 (a OUT INT)
+AS
+BEGIN
+PREPARE stmt FROM 'CALL p1(?)';
+EXECUTE stmt USING a;
+END;
+/
+SET @a= 1;
+CALL p2(@a);
+SELECT @a;
+@a
+10
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+#
+# Using a trigger field as a EXECUTE..USING out parameter
+#
+CREATE PROCEDURE p1 (a OUT INT)
+AS
+BEGIN
+a:= 10;
+END;
+/
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW CALL p1(:NEW.a);
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1;
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Testing re-prepare on a table metadata update between PREPARE and EXECUTE
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1(a IN INT)
+AS
+BEGIN
+INSERT INTO t1 VALUES (a);
+END;
+/
+PREPARE stmt FROM 'CALL p1(?)';
+EXECUTE stmt USING 10;
+SELECT * FROM t1;
+a
+10
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW NEW.a:=NEW.a+1;
+EXECUTE stmt USING 20;
+SELECT * FROM t1;
+a
+10
+21
+DEALLOCATE PREPARE stmt;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# End of MDEV-10709 Expressions as parameters to Dynamic SQL
+#
+#
+# MDEV-10585 EXECUTE IMMEDIATE statement
+#
+#
+# Testing disallowed expressions in USING
+#
+EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING (SELECT 1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+BEGIN
+RETURN 'test';
+END;
+$$
+EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
+ERROR 42000: EXECUTE..USING does not support subqueries or stored functions
+DROP FUNCTION f1;
+#
+# Testing simple expressions
+#
+EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING 10;
+:1
+10
+#
+# MDEV-10866 Extend PREPARE and EXECUTE IMMEDIATE to understand expressions
+#
+#
+# Testing erroneous and diallowed prepare source
+#
+EXECUTE IMMEDIATE _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL';
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle'
+PREPARE stmt FROM _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL';
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle'
+EXECUTE IMMEDIATE (SELECT 'SELECT 1');
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1
+PREPARE stmt FROM (SELECT 'SELECT 1');
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1
+EXECUTE IMMEDIATE a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+PREPARE stmt FROM a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+EXECUTE IMMEDIATE NULL;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
+PREPARE stmt FROM NULL;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
+EXECUTE IMMEDIATE COALESCE(NULL);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
+PREPARE stmt FROM COALESCE(NULL);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NULL' at line 1
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+BEGIN
+RETURN 't1';
+END;
+$$
+EXECUTE IMMEDIATE f1();
+ERROR 42000: EXECUTE IMMEDIATE does not support subqueries or stored functions
+PREPARE stmt FROM f1();
+ERROR 42000: PREPARE..FROM does not support subqueries or stored functions
+DROP FUNCTION f1;
+#
+# Testing user variables in prepare source
+#
+SET @table_name='DUAL';
+EXECUTE IMMEDIATE 'SELECT 1 AS a FROM ' || @table_name;
+a
+1
+PREPARE stmt FROM 'SELECT 1 AS a FROM ' || @table_name;
+EXECUTE stmt;
+a
+1
+DEALLOCATE PREPARE stmt;
+#
+# Testing SP parameters and variables in prepare source
+#
+CREATE PROCEDURE p1(table_name VARCHAR)
+AS
+BEGIN
+EXECUTE IMMEDIATE 'SELECT 1 AS c FROM '|| table_name;
+END;
+$$
+CALL p1('DUAL');
+c
+1
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+table_name VARCHAR(64):='DUAL';
+BEGIN
+EXECUTE IMMEDIATE 'SELECT 1 AS c FROM ' || table_name;
+END;
+$$
+CALL p1();
+c
+1
+DROP PROCEDURE p1;
+#
+# End of MDEV-10866 Extend PREPARE and EXECUTE IMMEDIATE to understand expressions
+#
diff --git a/mysql-test/suite/compat/oracle/r/sequence.result b/mysql-test/suite/compat/oracle/r/sequence.result
new file mode 100644
index 00000000000..dbbabc36683
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sequence.result
@@ -0,0 +1,77 @@
+SET sql_mode=ORACLE;
+CREATE SEQUENCE s1;
+SHOW CREATE SEQUENCE s1;
+Table Create Table
+s1 CREATE SEQUENCE "s1" start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle
+SELECT s1.currval;
+s1.currval
+NULL
+SELECT s1.nextval;
+s1.nextval
+1
+SELECT s1.nextval;
+s1.nextval
+2
+SELECT s1.nextval;
+s1.nextval
+3
+EXPLAIN EXTENDED SELECT s1.nextval;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select nextval("test"."s1") AS "s1.nextval"
+SELECT nextval(s1);
+nextval(s1)
+4
+EXPLAIN EXTENDED SELECT s1.currval;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select lastval("test"."s1") AS "s1.currval"
+SELECT lastval(s1);
+lastval(s1)
+4
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1;
+CREATE VIEW v1 AS SELECT s1.nextval AS a;
+SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1';
+VIEW_DEFINITION
+select nextval(`test`.`s1`) AS `a`
+SELECT * FROM v1;
+a
+1
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE VIEW "v1" AS select nextval("test"."s1") AS "a" latin1 latin1_swedish_ci
+DROP VIEW v1;
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1;
+CREATE VIEW v1 AS SELECT s1.currval AS a;
+SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1';
+VIEW_DEFINITION
+select lastval(`test`.`s1`) AS `a`
+SELECT * FROM v1;
+a
+NULL
+SHOW CREATE VIEW v1;
+View Create View character_set_client collation_connection
+v1 CREATE VIEW "v1" AS select lastval("test"."s1") AS "a" latin1 latin1_swedish_ci
+DROP VIEW v1;
+DROP SEQUENCE s1;
+#
+# MDEV-12533 sql_mode=ORACLE: Add support for database qualified sequence names in NEXTVAL and CURRVAL
+#
+CREATE SEQUENCE s1;
+SELECT test.s1.nextval;
+test.s1.nextval
+1
+SELECT test.s1.currval;
+test.s1.currval
+1
+SELECT .s1.nextval;
+.s1.nextval
+2
+SELECT .s1.currval;
+.s1.currval
+2
+DROP SEQUENCE s1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-anonymous.result b/mysql-test/suite/compat/oracle/r/sp-anonymous.result
new file mode 100644
index 00000000000..26bce0f435f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-anonymous.result
@@ -0,0 +1,220 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10655 Anonymous blocks
+#
+# Testing BEGIN NOT ATOMIC with no declarations
+BEGIN NOT ATOMIC
+SELECT 1 AS a;
+END
+/
+a
+1
+# Testing BEGIN NOT ATOMIC with declarations
+# DECLARE starts a new block and thus must be followed by BEGIN .. END
+BEGIN NOT ATOMIC
+DECLARE
+i INT DEFAULT 5;
+x INT DEFAULT 10;
+BEGIN
+<<label>>
+WHILE i > 3 LOOP
+i:= i - 1;
+SELECT i;
+END LOOP label;
+END;
+END
+/
+i
+4
+i
+3
+# Anonymous blocks with no declarations and no exceptions
+BEGIN
+SELECT 1 AS a;
+END
+$$
+a
+1
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+BEGIN
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(30);
+ROLLBACK;
+END;
+$$
+SELECT * FROM t1;
+a
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+BEGIN
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(30);
+END;
+$$
+ROLLBACK;
+SELECT * FROM t1;
+a
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+BEGIN
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(30);
+COMMIT;
+END;
+$$
+SELECT * FROM t1;
+a
+10
+20
+30
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+BEGIN
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(30);
+END;
+$$
+COMMIT;
+SELECT * FROM t1;
+a
+10
+20
+30
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+BEGIN
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(20);
+END;
+$$
+ERROR 23000: Duplicate entry '20' for key 'PRIMARY'
+COMMIT;
+SELECT * FROM t1;
+a
+10
+20
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+# Anonymous blocks with no declarations, with exceptions
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+BEGIN
+INSERT INTO t1 VALUES(20);
+INSERT INTO t1 VALUES(20);
+EXCEPTION
+WHEN DUP_VAL_ON_INDEX THEN NULL;
+END;
+$$
+COMMIT;
+SELECT * FROM t1;
+a
+10
+20
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+# Anonymous blocks with declarations, with no exceptions
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DECLARE
+a20 INT:=20;
+a30 INT:=30;
+BEGIN
+INSERT INTO t1 VALUES(a20);
+INSERT INTO t1 VALUES(a30);
+ROLLBACK;
+END;
+$$
+SELECT * FROM t1;
+a
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DECLARE
+a20 INT:=20;
+a30 INT:=30;
+BEGIN
+INSERT INTO t1 VALUES(a20);
+INSERT INTO t1 VALUES(a30);
+END;
+$$
+ROLLBACK;
+SELECT * FROM t1;
+a
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DECLARE
+a20 INT:=20;
+a30 INT:=30;
+BEGIN
+INSERT INTO t1 VALUES(a20);
+INSERT INTO t1 VALUES(a30);
+COMMIT;
+END;
+$$
+SELECT * FROM t1;
+a
+10
+20
+30
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DECLARE
+a20 INT:=20;
+a30 INT:=30;
+BEGIN
+INSERT INTO t1 VALUES(a20);
+INSERT INTO t1 VALUES(a30);
+END;
+$$
+COMMIT;
+SELECT * FROM t1;
+a
+10
+20
+30
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+# Anonymous blocks with declarations, with exceptions
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DECLARE
+a20 INT:=20;
+BEGIN
+INSERT INTO t1 VALUES(a20);
+INSERT INTO t1 VALUES(a20);
+EXCEPTION
+WHEN DUP_VAL_ON_INDEX THEN NULL;
+END;
+$$
+COMMIT;
+SELECT * FROM t1;
+a
+10
+20
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
diff --git a/mysql-test/suite/compat/oracle/r/sp-code.result b/mysql-test/suite/compat/oracle/r/sp-code.result
new file mode 100644
index 00000000000..1087e10552b
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-code.result
@@ -0,0 +1,1483 @@
+SET sql_mode=ORACLE;
+#
+# Testing exceptions in the top-level blocks
+#
+# No HANDLER declarations, no exceptions
+CREATE FUNCTION f1 RETURN INT
+AS
+BEGIN
+RETURN 10;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 freturn int 10
+SELECT f1();
+f1()
+10
+DROP FUNCTION f1;
+# No HANDLER declarations, no code, no exceptions
+CREATE PROCEDURE p1 ()
+IS
+BEGIN
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 jump 2
+CALL p1;
+DROP PROCEDURE p1;
+# No HANDLER declarations, no code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+EXCEPTION
+WHEN 1002 THEN v:=225;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 jump 1
+1 hpush_jump 4 1 EXIT
+2 set v@0 225
+3 hreturn 0 4
+4 hpop 1
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+@v
+10
+DROP PROCEDURE p1;
+# No HANDLER declarations, some code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=224;
+EXCEPTION
+WHEN 1002 THEN v:=225;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 jump 3
+1 set v@0 224
+2 jump 6
+3 hpush_jump 1 1 EXIT
+4 set v@0 225
+5 hreturn 0 6
+6 hpop 1
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+@v
+224
+DROP PROCEDURE p1;
+# Some HANDLER declarations, no code, no exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+EXIT HANDLER FOR 1000
+BEGIN
+v:=123;
+END;
+BEGIN
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 hpush_jump 3 1 EXIT
+1 set v@0 123
+2 hreturn 0 3
+3 hpop 1
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+@v
+10
+DROP PROCEDURE p1;
+# Some HANDLER declarations, no code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+EXIT HANDLER FOR 1000
+BEGIN
+v:=123;
+END;
+BEGIN
+EXCEPTION
+WHEN 1002 THEN v:=225;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 hpush_jump 3 1 EXIT
+1 set v@0 123
+2 hreturn 0 6
+3 hpush_jump 6 1 EXIT
+4 set v@0 225
+5 hreturn 0 6
+6 hpop 2
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+@v
+10
+DROP PROCEDURE p1;
+# Some HANDLER declarations, some code, no exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+EXIT HANDLER FOR 1000
+BEGIN
+v:=123;
+END;
+BEGIN
+v:=223;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 hpush_jump 3 1 EXIT
+1 set v@0 123
+2 hreturn 0 4
+3 set v@0 223
+4 hpop 1
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+@v
+223
+DROP PROCEDURE p1;
+# Some HANDLER declarations, some code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT VARCHAR2(20))
+IS
+EXIT HANDLER FOR 1000
+BEGIN
+v:=123;
+END;
+CONTINUE HANDLER FOR 1001
+BEGIN
+SET v=223;
+END;
+BEGIN
+v:= 1;
+EXCEPTION
+WHEN 1002 THEN SET v=225;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 hpush_jump 3 1 EXIT
+1 set v@0 123
+2 hreturn 0 12
+3 hpush_jump 8 1 CONTINUE
+4 set v@0 223
+5 hreturn 1
+6 set v@0 1
+7 jump 12
+8 hpush_jump 6 1 EXIT
+9 set v@0 225
+10 hreturn 0 12
+11 jump 6
+12 hpop 3
+DROP PROCEDURE p1;
+#
+# Testing EXCEPTIONS in internal blocks
+#
+# No HANDLER declarations, no code, no exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+BEGIN
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 jump 5
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+123
+DROP PROCEDURE p1;
+# No HANDLER declarations, no code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+BEGIN
+EXCEPTION
+WHEN 20002 THEN v:=335;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 jump 2
+2 hpush_jump 5 1 EXIT
+3 set v@0 335
+4 hreturn 0 5
+5 hpop 1
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+123
+DROP PROCEDURE p1;
+# No HANDLER declarations, some code, no exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+BEGIN
+v:=223;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 set v@0 223
+2 jump 6
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+223
+DROP PROCEDURE p1;
+# No HANDLER declarations, some code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+BEGIN
+v:=223;
+EXCEPTION
+WHEN 20002 THEN v:=335;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 jump 4
+2 set v@0 223
+3 jump 7
+4 hpush_jump 2 1 EXIT
+5 set v@0 335
+6 hreturn 0 7
+7 hpop 1
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+223
+DROP PROCEDURE p1;
+# Some HANDLER declarations, no code, no exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+DECLARE
+EXIT HANDLER FOR 1000
+BEGIN
+v:=323;
+END;
+BEGIN
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 hpush_jump 4 1 EXIT
+2 set v@0 323
+3 hreturn 0 4
+4 hpop 1
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+123
+DROP PROCEDURE p1;
+# Some HANDLER declarations, no code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+DECLARE
+EXIT HANDLER FOR 1000
+BEGIN
+v:=323;
+END;
+BEGIN
+EXCEPTION
+WHEN 20002 THEN v:=335;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 hpush_jump 4 1 EXIT
+2 set v@0 323
+3 hreturn 0 7
+4 hpush_jump 7 1 EXIT
+5 set v@0 335
+6 hreturn 0 7
+7 hpop 2
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+123
+DROP PROCEDURE p1;
+# Some HANDLER declarations, some code, no exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+DECLARE
+EXIT HANDLER FOR 1000
+BEGIN
+v:=323;
+END;
+BEGIN
+v:= 324;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 hpush_jump 4 1 EXIT
+2 set v@0 323
+3 hreturn 0 5
+4 set v@0 324
+5 hpop 1
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+324
+DROP PROCEDURE p1;
+# Some HANDLER declarations, some code, some exceptions
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+v:=123;
+DECLARE
+EXIT HANDLER FOR 1000
+BEGIN
+v:=323;
+END;
+BEGIN
+v:= 324;
+EXCEPTION WHEN 2002 THEN v:= 325;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v@0 123
+1 hpush_jump 6 1 EXIT
+2 set v@0 323
+3 hreturn 0 9
+4 set v@0 324
+5 jump 9
+6 hpush_jump 4 1 EXIT
+7 set v@0 325
+8 hreturn 0 9
+9 hpop 2
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+324
+DROP PROCEDURE p1;
+#
+# Testing EXIT statement
+#
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+LOOP
+i:= i + 1;
+IF i >= 5 THEN
+EXIT;
+END IF;
+END LOOP;
+RETURN i;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set i@0 0
+1 set i@0 i@0 + 1
+2 jump_if_not 1(1) i@0 >= 5
+3 jump 4
+4 freturn int i@0
+SELECT f1() FROM DUAL;
+f1()
+5
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+LOOP
+i:= i + 1;
+EXIT WHEN i >=5;
+END LOOP;
+RETURN i;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set i@0 0
+1 set i@0 i@0 + 1
+2 jump_if_not 1(0) i@0 >= 5
+3 jump 4
+4 freturn int i@0
+SELECT f1() FROM DUAL;
+f1()
+5
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+LOOP
+BEGIN
+i:= i + 1;
+IF i >= 5 THEN
+EXIT;
+END IF;
+EXCEPTION
+WHEN OTHERS THEN i:= 1000;
+END;
+END LOOP;
+RETURN i;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set i@0 0
+1 jump 5
+2 set i@0 i@0 + 1
+3 jump_if_not 8(8) i@0 >= 5
+4 jump 10
+5 hpush_jump 2 1 EXIT
+6 set i@0 1000
+7 hreturn 0 8
+8 hpop 1
+9 jump 5
+10 freturn int i@0
+SELECT f1() FROM DUAL;
+f1()
+5
+DROP FUNCTION f1;
+CREATE PROCEDURE p1(a IN OUT INT)
+IS
+i INT := 0;
+BEGIN
+LOOP
+LOOP
+BEGIN
+i:= i + 1;
+IF i >=5 THEN
+EXIT;
+END IF;
+EXCEPTION
+WHEN OTHERS THEN a:=1000;
+END;
+END LOOP;
+i:= i + 100;
+EXIT;
+END LOOP;
+a:= i;
+EXCEPTION
+WHEN OTHERS THEN a:=11;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set i@1 0
+1 jump 14
+2 set i@1 i@1 + 1
+3 jump_if_not 8(8) i@1 >= 5
+4 jump 10
+5 hpush_jump 2 2 EXIT
+6 set a@0 1000
+7 hreturn 0 8
+8 hpop 1
+9 jump 5
+10 set i@1 i@1 + 100
+11 jump 12
+12 set a@0 i@1
+13 jump 17
+14 hpush_jump 5 2 EXIT
+15 set a@0 11
+16 hreturn 0 17
+17 hpop 1
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+@v
+105
+DROP PROCEDURE p1;
+# Testing RETURN in procedures
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+IF a < 10 THEN
+BEGIN
+a:= a + 1;
+RETURN;
+END;
+END IF;
+a:= 200;
+EXCEPTION
+WHEN OTHERS THEN
+BEGIN
+a:= 100;
+RETURN;
+END;
+END;
+/
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 jump 6
+1 jump_if_not 4(4) a@0 < 10
+2 set a@0 a@0 + 1
+3 preturn
+4 set a@0 200
+5 jump 9
+6 hpush_jump 1 1 EXIT
+7 set a@0 100
+8 preturn
+9 hpop 1
+DROP PROCEDURE p1;
+# Testing FOR loop statement
+CREATE FUNCTION f1 (a INT, b INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+FOR i IN 1 .. a
+LOOP
+total:= total + i;
+IF i = b THEN
+EXIT;
+END IF;
+END LOOP;
+RETURN total;
+END
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@2 0
+1 set i@3 1
+2 set [upper_bound]@4 a@0
+3 jump_if_not 9(9) i@3 <= [upper_bound]@4
+4 set total@2 total@2 + i@3
+5 jump_if_not 7(7) i@3 = b@1
+6 jump 9
+7 set i@3 i@3 + 1
+8 jump 3
+9 freturn int total@2
+SELECT f1(3, 100) FROM DUAL;
+f1(3, 100)
+6
+SELECT f1(3, 2) FROM DUAL;
+f1(3, 2)
+3
+DROP FUNCTION f1;
+CREATE FUNCTION f1 (a INT, b INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+FOR i IN REVERSE a..1
+LOOP
+total:= total + i;
+IF i = b THEN
+EXIT;
+END IF;
+END LOOP;
+RETURN total;
+END
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@2 0
+1 set i@3 a@0
+2 set [upper_bound]@4 1
+3 jump_if_not 9(9) i@3 >= [upper_bound]@4
+4 set total@2 total@2 + i@3
+5 jump_if_not 7(7) i@3 = b@1
+6 jump 9
+7 set i@3 i@3 + -1
+8 jump 3
+9 freturn int total@2
+SELECT f1(3, 100) FROM DUAL;
+f1(3, 100)
+6
+SELECT f1(3, 2) FROM DUAL;
+f1(3, 2)
+5
+DROP FUNCTION f1;
+# Testing labeled FOR LOOP statement
+CREATE FUNCTION f1 (a INT, limita INT, b INT, limitb INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+<<la>>
+FOR ia IN 1 .. a
+LOOP
+total:= total + 1000;
+<<lb>>
+FOR ib IN 1 .. b
+LOOP
+total:= total + 1;
+EXIT lb WHEN ib = limitb;
+EXIT la WHEN ia = limita;
+END LOOP lb;
+END LOOP la;
+RETURN total;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@4 0
+1 set ia@5 1
+2 set [upper_bound]@6 a@0
+3 jump_if_not 17(17) ia@5 <= [upper_bound]@6
+4 set total@4 total@4 + 1000
+5 set ib@7 1
+6 set [upper_bound]@8 b@2
+7 jump_if_not 15(15) ib@7 <= [upper_bound]@8
+8 set total@4 total@4 + 1
+9 jump_if_not 11(0) ib@7 = limitb@3
+10 jump 15
+11 jump_if_not 13(0) ia@5 = limita@1
+12 jump 17
+13 set ib@7 ib@7 + 1
+14 jump 7
+15 set ia@5 ia@5 + 1
+16 jump 3
+17 freturn int total@4
+SELECT f1(2, 1, 2, 2) FROM DUAL;
+f1(2, 1, 2, 2)
+1001
+SELECT f1(2, 2, 2, 2) FROM DUAL;
+f1(2, 2, 2, 2)
+2003
+SELECT f1(2, 3, 2, 3) FROM DUAL;
+f1(2, 3, 2, 3)
+2004
+DROP FUNCTION f1;
+# Testing labeled ITERATE in a labeled FOR LOOP
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+<<li>>
+FOR i IN 1 .. a
+LOOP
+total:= total + 1000;
+IF i = 5 THEN
+ITERATE li;
+END IF;
+total:= total + 1;
+END LOOP;
+RETURN total;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@1 0
+1 set i@2 1
+2 set [upper_bound]@3 a@0
+3 jump_if_not 11(11) i@2 <= [upper_bound]@3
+4 set total@1 total@1 + 1000
+5 jump_if_not 8(8) i@2 = 5
+6 set i@2 i@2 + 1
+7 jump 3
+8 set total@1 total@1 + 1
+9 set i@2 i@2 + 1
+10 jump 3
+11 freturn int total@1
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+f1(3) f1(4) f1(5) f1(6)
+3003 4004 5004 6005
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+<<li>>
+FOR i IN 1 .. a
+LOOP
+FOR j IN 1 .. 2
+LOOP
+total:= total + 1000;
+IF i = 5 THEN
+ITERATE li;
+END IF;
+total:= total + 1;
+END LOOP;
+END LOOP;
+RETURN total;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@1 0
+1 set i@2 1
+2 set [upper_bound]@3 a@0
+3 jump_if_not 16(16) i@2 <= [upper_bound]@3
+4 set j@4 1
+5 set [upper_bound]@5 2
+6 jump_if_not 14(14) j@4 <= [upper_bound]@5
+7 set total@1 total@1 + 1000
+8 jump_if_not 11(11) i@2 = 5
+9 set i@2 i@2 + 1
+10 jump 3
+11 set total@1 total@1 + 1
+12 set j@4 j@4 + 1
+13 jump 6
+14 set i@2 i@2 + 1
+15 jump 3
+16 freturn int total@1
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+f1(3) f1(4) f1(5) f1(6)
+6006 8008 9008 11010
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+<<lj>>
+FOR j IN 1 .. 2
+LOOP
+<<li>>
+FOR i IN 1 .. a
+LOOP
+total:= total + 1000;
+IF i = 5 THEN
+ITERATE li;
+END IF;
+total:= total + 1;
+END LOOP;
+END LOOP;
+RETURN total;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@1 0
+1 set j@2 1
+2 set [upper_bound]@3 2
+3 jump_if_not 16(16) j@2 <= [upper_bound]@3
+4 set i@4 1
+5 set [upper_bound]@5 a@0
+6 jump_if_not 14(14) i@4 <= [upper_bound]@5
+7 set total@1 total@1 + 1000
+8 jump_if_not 11(11) i@4 = 5
+9 set i@4 i@4 + 1
+10 jump 6
+11 set total@1 total@1 + 1
+12 set i@4 i@4 + 1
+13 jump 6
+14 set j@2 j@2 + 1
+15 jump 3
+16 freturn int total@1
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+f1(3) f1(4) f1(5) f1(6)
+6006 8008 10008 12010
+DROP FUNCTION f1;
+# Testing CONTINUE statement
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+FOR i IN 1 .. a
+LOOP
+CONTINUE WHEN i=5;
+total:= total + 1;
+END LOOP;
+RETURN total;
+END;
+/
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set total@1 0
+1 set i@2 1
+2 set [upper_bound]@3 a@0
+3 jump_if_not 10(10) i@2 <= [upper_bound]@3
+4 jump_if_not 7(0) i@2 = 5
+5 set i@2 i@2 + 1
+6 jump 3
+7 set total@1 total@1 + 1
+8 set i@2 i@2 + 1
+9 jump 3
+10 freturn int total@1
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+f1(3) f1(4) f1(5) f1(6)
+3 4 4 5
+DROP FUNCTION f1;
+#
+# Start of MDEV-10597 Cursors with parameters
+#
+CREATE PROCEDURE p1(arg_value_a VARCHAR, arg_value_b VARCHAR,
+arg_pattern_a VARCHAR, arg_pattern_b VARCHAR)
+AS
+v_a VARCHAR(10);
+v_b VARCHAR(20);
+CURSOR c (p_value_a VARCHAR,
+p_value_b VARCHAR,
+p_pattern_a VARCHAR,
+p_pattern_b VARCHAR,
+p_limit_a INT,
+p_limit_b INT,
+p_unused TEXT) IS
+(SELECT p_value_a, p_value_b FROM DUAL
+WHERE p_value_a LIKE p_pattern_a LIMIT p_limit_a)
+UNION
+(SELECT p_value_b, p_value_a FROM DUAL
+WHERE p_value_b LIKE p_pattern_b LIMIT p_limit_b);
+BEGIN
+OPEN c(arg_value_a, (SELECT arg_value_b),
+arg_pattern_a, arg_pattern_b, 100, 101, 'x');
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+SELECT v_a, v_b;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('aaa','bbb','aaa','bbb');
+v_a v_b
+aaa bbb
+v_a v_b
+bbb aaa
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set v_a@4 NULL
+1 set v_b@5 NULL
+2 cpush c@0
+3 set p_value_a@6 arg_value_a@0
+4 set p_value_b@7 (select arg_value_b@1)
+5 set p_pattern_a@8 arg_pattern_a@2
+6 set p_pattern_b@9 arg_pattern_b@3
+7 set p_limit_a@10 100
+8 set p_limit_b@11 101
+9 set p_unused@12 'x'
+10 copen c@0
+11 cfetch c@0 v_a@4 v_b@5
+12 jump_if_not 14(0) "c"%NOTFOUND
+13 jump 16
+14 stmt 0 "SELECT v_a, v_b"
+15 jump 11
+16 cclose c@0
+17 cpop 1
+DROP PROCEDURE p1;
+#
+# End of MDEV-10597 Cursors with parameters
+#
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+CREATE FUNCTION f1() RETURN INT
+AS
+a ROW(a INT, b INT);
+BEGIN
+a.b:= 200;
+RETURN a.b;
+END;
+$$
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set a@0 NULL
+1 set a.b@0[1] 200
+2 freturn int a.b@0[1]
+SELECT f1();
+f1()
+200
+DROP FUNCTION f1;
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+rec:= ROW(10,20.123456,30.123,'test');
+SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec@0 NULL
+1 set rec@0 (10,20.123456,30.123,'test')
+2 stmt 0 "SELECT rec.a, rec.b, rec.c, rec.d"
+CALL p1;
+rec.a rec.b rec.c rec.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ROW(10,20.123456,30.123,'test');
+BEGIN
+SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec@0 (10,20.123456,30.123,'test')
+1 stmt 0 "SELECT rec.a, rec.b, rec.c, rec.d"
+CALL p1;
+rec.a rec.b rec.c rec.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+rec1:= ROW(10,20.123456,30.123,'test');
+rec2:= rec1;
+SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec1@0 NULL
+1 set rec2@1 NULL
+2 set rec1@0 (10,20.123456,30.123,'test')
+3 set rec2@1 rec1@0
+4 stmt 0 "SELECT rec2.a, rec2.b, rec2.c, rec2.d"
+CALL p1;
+rec2.a rec2.b rec2.c rec2.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ROW(10,20.123456,30.123,'test');
+rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) := rec1;
+BEGIN
+SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec1@0 (10,20.123456,30.123,'test')
+1 set rec2@1 rec1@0
+2 stmt 0 "SELECT rec2.a, rec2.b, rec2.c, rec2.d"
+CALL p1;
+rec2.a rec2.b rec2.c rec2.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
+#
+# MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+rec1.a:= 10;
+rec1.b:= 'bbb';
+rec1.c:= 10e2;
+rec1.d:= 10.12;
+rec1.c:= rec1.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec1@0 NULL
+1 set rec1.a@0["a"] 10
+2 set rec1.b@0["b"] 'bbb'
+3 set rec1.c@0["c"] 10e2
+4 set rec1.d@0["d"] 10.12
+5 set rec1.c@0["c"] rec1.d@0["d"]
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1,rec2 cur1%ROWTYPE;
+rec3 cur2%ROWTYPE;
+BEGIN
+rec1.a:= 10;
+rec1.b:= 'bbb';
+END;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 cpush cur1@0
+1 cpush cur2@1
+2 cursor_copy_struct cur1 rec1@0
+3 set rec1@0 NULL
+4 cursor_copy_struct cur1 rec2@1
+5 set rec2@1 NULL
+6 cursor_copy_struct cur2 rec3@2
+7 set rec3@2 NULL
+8 set rec1.a@0["a"] 10
+9 set rec1.b@0["b"] 'bbb'
+10 jump 11
+11 cpop 2
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-10581 sql_mode=ORACLE: Explicit cursor FOR LOOP
+#
+CREATE PROCEDURE p1
+AS
+CURSOR cur0 IS SELECT 10 AS a, 'b0' AS b;
+CURSOR cur1 IS SELECT 10 AS a, 'b0' AS b;
+CURSOR cur2 IS SELECT 10 AS a, 'b0' AS b;
+BEGIN
+FOR rec1 IN cur1
+LOOP
+SELECT rec1.a, rec1.b;
+rec1.a:= 11;
+rec1.b:= 'b1';
+SELECT rec1.a, rec1.b;
+END LOOP;
+FOR rec0 IN cur0
+LOOP
+rec0.a:= 10;
+rec0.b:='b0';
+END LOOP;
+FOR rec2 IN cur2
+LOOP
+rec2.a:= 10;
+rec2.b:='b0';
+END LOOP;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 cpush cur0@0
+1 cpush cur1@1
+2 cpush cur2@2
+3 cursor_copy_struct cur1 rec1@0
+4 copen cur1@1
+5 cfetch cur1@1 rec1@0
+6 jump_if_not 13(13) "cur1"%FOUND
+7 stmt 0 "SELECT rec1.a, rec1.b"
+8 set rec1.a@0["a"] 11
+9 set rec1.b@0["b"] 'b1'
+10 stmt 0 "SELECT rec1.a, rec1.b"
+11 cfetch cur1@1 rec1@0
+12 jump 6
+13 cursor_copy_struct cur0 rec0@1
+14 copen cur0@0
+15 cfetch cur0@0 rec0@1
+16 jump_if_not 21(21) "cur0"%FOUND
+17 set rec0.a@1["a"] 10
+18 set rec0.b@1["b"] 'b0'
+19 cfetch cur0@0 rec0@1
+20 jump 16
+21 cursor_copy_struct cur2 rec2@2
+22 copen cur2@2
+23 cfetch cur2@2 rec2@2
+24 jump_if_not 29(29) "cur2"%FOUND
+25 set rec2.a@2["a"] 10
+26 set rec2.b@2["b"] 'b0'
+27 cfetch cur2@2 rec2@2
+28 jump 24
+29 cpop 3
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+CURSOR cur0 IS SELECT 10 AS a, 'b0' AS b;
+BEGIN
+FOR rec0 IN cur0
+LOOP
+DECLARE
+CURSOR cur1 IS SELECT 11 AS a, 'b1' AS b;
+BEGIN
+rec0.a:= 11;
+rec0.b:= 'b0';
+FOR rec1 IN cur1
+LOOP
+rec1.a:= 11;
+rec1.b:= 'b1';
+DECLARE
+CURSOR cur2 IS SELECT 12 AS a, 'b2' AS b;
+BEGIN
+FOR rec2 IN cur2
+LOOP
+rec2.a:=12;
+rec2.b:='b2';
+END LOOP;
+END;
+END LOOP;
+END;
+END LOOP;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 cpush cur0@0
+1 cursor_copy_struct cur0 rec0@0
+2 copen cur0@0
+3 cfetch cur0@0 rec0@0
+4 jump_if_not 29(29) "cur0"%FOUND
+5 cpush cur1@1
+6 set rec0.a@0["a"] 11
+7 set rec0.b@0["b"] 'b0'
+8 cursor_copy_struct cur1 rec1@1
+9 copen cur1@1
+10 cfetch cur1@1 rec1@1
+11 jump_if_not 26(26) "cur1"%FOUND
+12 set rec1.a@1["a"] 11
+13 set rec1.b@1["b"] 'b1'
+14 cpush cur2@2
+15 cursor_copy_struct cur2 rec2@2
+16 copen cur2@2
+17 cfetch cur2@2 rec2@2
+18 jump_if_not 23(23) "cur2"%FOUND
+19 set rec2.a@2["a"] 12
+20 set rec2.b@2["b"] 'b2'
+21 cfetch cur2@2 rec2@2
+22 jump 18
+23 cpop 1
+24 cfetch cur1@1 rec1@1
+25 jump 11
+26 cpop 1
+27 cfetch cur0@0 rec0@0
+28 jump 4
+29 cpop 1
+DROP PROCEDURE p1;
+#
+# MDEV-12098 sql_mode=ORACLE: Implicit cursor FOR loop
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+FOR rec1 IN (SELECT 11 AS a, 'b1' AS b)
+LOOP
+SELECT rec1.a, rec1.b;
+rec1.a:= 11;
+rec1.b:= 'b1';
+SELECT rec1.a, rec1.b;
+END LOOP;
+FOR rec0 IN (SELECT 10 AS a, 'b0' AS b)
+LOOP
+rec0.a:= 10;
+rec0.b:='b0';
+END LOOP;
+FOR rec2 IN (SELECT 12 AS a, 'b2' AS b)
+LOOP
+rec2.a:= 10;
+rec2.b:='b0';
+END LOOP;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 cpush [implicit_cursor]@0
+1 cursor_copy_struct [implicit_cursor] rec1@0
+2 copen [implicit_cursor]@0
+3 cfetch [implicit_cursor]@0 rec1@0
+4 jump_if_not 11(11) "[implicit_cursor]"%FOUND
+5 stmt 0 "SELECT rec1.a, rec1.b"
+6 set rec1.a@0["a"] 11
+7 set rec1.b@0["b"] 'b1'
+8 stmt 0 "SELECT rec1.a, rec1.b"
+9 cfetch [implicit_cursor]@0 rec1@0
+10 jump 4
+11 cpop 1
+12 cpush [implicit_cursor]@0
+13 cursor_copy_struct [implicit_cursor] rec0@1
+14 copen [implicit_cursor]@0
+15 cfetch [implicit_cursor]@0 rec0@1
+16 jump_if_not 21(21) "[implicit_cursor]"%FOUND
+17 set rec0.a@1["a"] 10
+18 set rec0.b@1["b"] 'b0'
+19 cfetch [implicit_cursor]@0 rec0@1
+20 jump 16
+21 cpop 1
+22 cpush [implicit_cursor]@0
+23 cursor_copy_struct [implicit_cursor] rec2@2
+24 copen [implicit_cursor]@0
+25 cfetch [implicit_cursor]@0 rec2@2
+26 jump_if_not 31(31) "[implicit_cursor]"%FOUND
+27 set rec2.a@2["a"] 10
+28 set rec2.b@2["b"] 'b0'
+29 cfetch [implicit_cursor]@0 rec2@2
+30 jump 26
+31 cpop 1
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+FOR rec0 IN (SELECT 10 AS a, 'b0' AS b)
+LOOP
+rec0.a:= 11;
+rec0.b:= 'b0';
+FOR rec1 IN (SELECT 11 AS a, 'b1' AS b)
+LOOP
+rec1.a:= 11;
+rec1.b:= 'b1';
+FOR rec2 IN (SELECT 12 AS a, 'b2' AS b)
+LOOP
+rec2.a:=12;
+rec2.b:='b2';
+END LOOP;
+END LOOP;
+END LOOP;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 cpush [implicit_cursor]@0
+1 cursor_copy_struct [implicit_cursor] rec0@0
+2 copen [implicit_cursor]@0
+3 cfetch [implicit_cursor]@0 rec0@0
+4 jump_if_not 29(29) "[implicit_cursor]"%FOUND
+5 set rec0.a@0["a"] 11
+6 set rec0.b@0["b"] 'b0'
+7 cpush [implicit_cursor]@1
+8 cursor_copy_struct [implicit_cursor] rec1@1
+9 copen [implicit_cursor]@1
+10 cfetch [implicit_cursor]@1 rec1@1
+11 jump_if_not 26(26) "[implicit_cursor]"%FOUND
+12 set rec1.a@1["a"] 11
+13 set rec1.b@1["b"] 'b1'
+14 cpush [implicit_cursor]@2
+15 cursor_copy_struct [implicit_cursor] rec2@2
+16 copen [implicit_cursor]@2
+17 cfetch [implicit_cursor]@2 rec2@2
+18 jump_if_not 23(23) "[implicit_cursor]"%FOUND
+19 set rec2.a@2["a"] 12
+20 set rec2.b@2["b"] 'b2'
+21 cfetch [implicit_cursor]@2 rec2@2
+22 jump 18
+23 cpop 1
+24 cfetch [implicit_cursor]@1 rec1@1
+25 jump 11
+26 cpop 1
+27 cfetch [implicit_cursor]@0 rec0@0
+28 jump 4
+29 cpop 1
+DROP PROCEDURE p1;
+#
+# MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations
+#
+#
+# Cursor declaration and cursor%ROWTYPE declaration in the same block
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'a');
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT a FROM t1;
+rec1 cur1%ROWTYPE;
+BEGIN
+rec1.a:= 10;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 cursor_copy_struct cur1 rec1@0
+1 set rec1@0 NULL
+2 cpush cur1@0
+3 set rec1.a@0["a"] 10
+4 cpop 1
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Recursive cursor and cursor%ROWTYPE declarations in the same block
+#
+CREATE PROCEDURE p1
+AS
+a INT:=10;
+CURSOR cur1 IS SELECT a;
+rec1 cur1%ROWTYPE;
+CURSOR cur2 IS SELECT rec1.a + 1 "a";
+rec2 cur2%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SELECT rec1.a;
+open cur2;
+FETCH cur2 INTO rec2;
+CLOSE cur2;
+SELECT rec2.a;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set a@0 10
+1 cursor_copy_struct cur1 rec1@1
+2 set rec1@1 NULL
+3 cursor_copy_struct cur2 rec2@2
+4 set rec2@2 NULL
+5 cpush cur1@0
+6 cpush cur2@1
+7 copen cur1@0
+8 cfetch cur1@0 rec1@1
+9 cclose cur1@0
+10 stmt 0 "SELECT rec1.a"
+11 copen cur2@1
+12 cfetch cur2@1 rec2@2
+13 cclose cur2@1
+14 stmt 0 "SELECT rec2.a"
+15 cpop 2
+CALL p1();
+rec1.a
+10
+rec2.a
+11
+DROP PROCEDURE p1;
+#
+# MDEV-12441 Variables declared after cursors with parameters lose values
+#
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 INT:=101;
+BEGIN
+OPEN cur(10,11);
+CLOSE cur;
+SELECT x0, x1;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set x0@0 100
+1 set x1@3 101
+2 cpush cur@0
+3 set cp1@1 10
+4 set cp2@2 11
+5 copen cur@0
+6 cclose cur@0
+7 stmt 0 "SELECT x0, x1"
+8 cpop 1
+CALL p1();
+x0 x1
+100 101
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur0(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 INT:=101;
+CURSOR cur1(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x2 INT:=102;
+CURSOR cur2(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x3 INT:=103;
+BEGIN
+OPEN cur0(0,1);
+CLOSE cur0;
+SELECT x0, x1, x2, x3;
+OPEN cur1(10,11);
+CLOSE cur1;
+SELECT x0, x1, x2, x3;
+OPEN cur2(20,21);
+CLOSE cur2;
+SELECT x0, x1, x2, x3;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set x0@0 100
+1 set x1@3 101
+2 set x2@6 102
+3 set x3@9 103
+4 cpush cur0@0
+5 cpush cur1@1
+6 cpush cur2@2
+7 set cp1@1 0
+8 set cp2@2 1
+9 copen cur0@0
+10 cclose cur0@0
+11 stmt 0 "SELECT x0, x1, x2, x3"
+12 set cp1@4 10
+13 set cp2@5 11
+14 copen cur1@1
+15 cclose cur1@1
+16 stmt 0 "SELECT x0, x1, x2, x3"
+17 set cp1@7 20
+18 set cp2@8 21
+19 copen cur2@2
+20 cclose cur2@2
+21 stmt 0 "SELECT x0, x1, x2, x3"
+22 cpop 3
+CALL p1();
+x0 x1 x2 x3
+100 101 102 103
+x0 x1 x2 x3
+100 101 102 103
+x0 x1 x2 x3
+100 101 102 103
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 t1.a%TYPE:=101;
+BEGIN
+OPEN cur(10,11);
+CLOSE cur;
+SELECT x0, x1;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set x0@0 100
+1 set x1@3 101
+2 cpush cur@0
+3 set cp1@1 10
+4 set cp2@2 11
+5 copen cur@0
+6 cclose cur@0
+7 stmt 0 "SELECT x0, x1"
+8 cpop 1
+CALL p1();
+x0 x1
+100 101
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 ROW(a INT,b INT):=ROW(101,102);
+BEGIN
+OPEN cur(10,11);
+CLOSE cur;
+SELECT x0, x1.a, x1.b;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set x0@0 100
+1 set x1@3 (101,102)
+2 cpush cur@0
+3 set cp1@1 10
+4 set cp2@2 11
+5 copen cur@0
+6 cclose cur@0
+7 stmt 0 "SELECT x0, x1.a, x1.b"
+8 cpop 1
+CALL p1();
+x0 x1.a x1.b
+100 101 102
+DROP PROCEDURE p1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor-decl.result b/mysql-test/suite/compat/oracle/r/sp-cursor-decl.result
new file mode 100644
index 00000000000..b75b5d5be9d
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-cursor-decl.result
@@ -0,0 +1,290 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations
+#
+#
+# Variable after cursor declaration
+#
+CREATE TABLE t1 (a INT);
+insert into t1 values (1);
+insert into t1 values (2);
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT a FROM t1;
+var1 varchar(10);
+BEGIN
+OPEN c;
+fetch c into var1;
+SELECT c%ROWCOUNT,var1;
+close c;
+END;
+$$
+CALL p1;
+c%ROWCOUNT var1
+1 1
+DROP PROCEDURE p1;
+drop table t1;
+#
+# Variable after condition declaration
+#
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+CREATE PROCEDURE p1
+AS
+dup_key CONDITION FOR SQLSTATE '23000';
+var1 varchar(40);
+CONTINUE HANDLER FOR dup_key
+BEGIN
+var1:='duplicate key in index';
+END;
+BEGIN
+var1:='';
+insert into t1 values (1);
+select var1;
+END;
+$$
+CALL p1;
+var1
+duplicate key in index
+DROP PROCEDURE p1;
+drop table t1;
+#
+# Condition after cursor declaration
+#
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+CREATE PROCEDURE p1
+AS
+var1 varchar(40);
+var2 integer;
+CURSOR c IS SELECT col1 FROM t1;
+dup_key CONDITION FOR SQLSTATE '23000';
+CONTINUE HANDLER FOR dup_key
+BEGIN
+var1:='duplicate key in index';
+END;
+BEGIN
+var1:='';
+insert into t1 values (1);
+SELECT var1;
+END;
+$$
+CALL p1;
+var1
+duplicate key in index
+DROP PROCEDURE p1;
+drop table t1;
+#
+# Cursor after handler declaration
+#
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+CREATE PROCEDURE p1
+AS
+var1 varchar(40);
+var2 integer;
+dup_key CONDITION FOR SQLSTATE '23000';
+CONTINUE HANDLER FOR dup_key
+BEGIN
+var1:='duplicate key in index';
+END;
+CURSOR c IS SELECT col1 FROM t1;
+BEGIN
+var1:='';
+insert into t1 values (1);
+SELECT var1;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CURSOR c IS SELECT col1 FROM t1;
+BEGIN
+var1:='';
+insert into t1 values (1);
+SELE' at line 10
+drop table t1;
+#
+# Condition after handler declaration
+#
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+CREATE PROCEDURE p1
+AS
+var1 varchar(40);
+var2 integer;
+dup_key CONDITION FOR SQLSTATE '23000';
+CURSOR c IS SELECT col1 FROM t1;
+CONTINUE HANDLER FOR dup_key
+BEGIN
+var1:='duplicate key in index';
+END;
+divide_by_zero CONDITION FOR SQLSTATE '22012';
+BEGIN
+var1:='';
+insert into t1 values (1);
+SELECT var1;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'divide_by_zero CONDITION FOR SQLSTATE '22012';
+BEGIN
+var1:='';
+insert into t1 va' at line 11
+drop table t1;
+#
+# Variable after handler declaration
+#
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+CREATE PROCEDURE p1
+AS
+var1 varchar(40);
+var2 integer;
+dup_key CONDITION FOR SQLSTATE '23000';
+CURSOR c IS SELECT col1 FROM t1;
+CONTINUE HANDLER FOR dup_key
+BEGIN
+var1:='duplicate key in index';
+END;
+divide_by_zero CONDITION FOR SQLSTATE '22012';
+BEGIN
+var1:='';
+insert into t1 values (1);
+SELECT var1;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'divide_by_zero CONDITION FOR SQLSTATE '22012';
+BEGIN
+var1:='';
+insert into t1 va' at line 11
+drop table t1;
+#
+# Variable after cursor (inner block)
+#
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+insert into t1 values (2);
+create unique index t1_col1 on t1 (col1);
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT col1 FROM t1;
+var1 varchar(40);
+BEGIN
+OPEN c;
+begin
+declare
+CURSOR c IS SELECT col1 FROM t1 where col1=2;
+var2 integer;
+dup_key CONDITION FOR SQLSTATE '23000';
+CONTINUE HANDLER FOR dup_key
+BEGIN
+var1:='duplicate key in index';
+END;
+begin
+OPEN c;
+fetch c into var1;
+SELECT 'inner cursor',var1;
+insert into t1 values (2);
+close c;
+end;
+end;
+SELECT var1;
+fetch c into var1;
+SELECT c%ROWCOUNT,var1;
+begin
+insert into t1 values (2);
+exception when 1062 then
+begin
+SELECT 'dup key caugth';
+end;
+end;
+close c;
+END;
+$$
+CALL p1;
+inner cursor var1
+inner cursor 2
+var1
+duplicate key in index
+c%ROWCOUNT var1
+1 1
+dup key caugth
+dup key caugth
+DROP PROCEDURE p1;
+drop table t1;
+#
+# Cursor declaration and row type declaration in same block
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+insert into t1 values(1,'a');
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT a FROM t1;
+rec1 cur1%ROWTYPE;
+BEGIN
+rec1.a:= 10;
+END;
+$$
+call p1;
+DROP PROCEDURE p1;
+drop table t1;
+#
+# Recursive cursor and cursor%ROWTYPE declarations in the same block
+#
+CREATE PROCEDURE p1
+AS
+a INT:=10;
+b VARCHAR(10):='b0';
+c DOUBLE:=0.1;
+CURSOR cur1 IS SELECT a, b, c;
+rec1 cur1%ROWTYPE;
+CURSOR cur2 IS SELECT rec1.a + 1 "a", rec1.b||'0' AS b, rec1.c AS c;
+rec2 cur2%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SELECT rec1.a;
+OPEN cur2;
+FETCH cur2 INTO rec2;
+CLOSE cur2;
+SELECT rec2.a;
+CREATE TABLE t2 AS SELECT rec2.a AS a, rec2.b AS b, rec2.c AS c;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+rec1.a
+10
+rec2.a
+11
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" bigint(20) DEFAULT NULL,
+ "b" varchar(11) DEFAULT NULL,
+ "c" double DEFAULT NULL
+)
+DROP PROCEDURE p1;
+#
+# MDEV-12916 Wrong column data type for an INT field of a cursor-anchored ROW variable
+#
+CREATE PROCEDURE p1
+AS
+a INT DEFAULT 10;
+CURSOR cur1 IS SELECT a;
+rec1 cur1%ROWTYPE;
+BEGIN
+CREATE TABLE t1 AS SELECT rec1.a;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+END;
+$$
+CALL p1();
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "rec1.a" int(11) DEFAULT NULL
+)
+DROP PROCEDURE p1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result
new file mode 100644
index 00000000000..726f8bcf9ca
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result
@@ -0,0 +1,1332 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
+#
+#
+# A complete working example
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+CREATE PROCEDURE p1 AS
+CURSOR c IS SELECT a,b FROM t1;
+BEGIN
+DECLARE
+rec c%ROWTYPE;
+BEGIN
+OPEN c;
+LOOP
+FETCH c INTO rec;
+EXIT WHEN c%NOTFOUND;
+SELECT 'rec=(' || rec.a ||','|| rec.b||')' AS c FROM dual;
+INSERT INTO t2 VALUES (rec.a, rec.b);
+END LOOP;
+CLOSE c;
+END;
+END;
+$$
+CALL p1();
+c
+rec=(10,b10)
+c
+rec=(20,b20)
+c
+rec=(30,b30)
+SELECT * FROM t2;
+a b
+10 b10
+20 b20
+30 b30
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# cursor%ROWTYPE referring to a table in a non-existing database
+#
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM tes2.t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+NULL;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'tes2.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+ERROR 42S02: Table 'tes2.t1' doesn't exist
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# cursor%ROWTYPE referring to a table in the current database
+#
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP TABLE t1;
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+DROP PROCEDURE p1;
+#
+# cursor%ROWTYPE referring to a table in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM test.t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Cursor%ROWTYPE referring to a view in the current database
+#
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM v1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# cursor%ROWTYPE referring to a view in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM test.v1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Checking that all cursor%ROWTYPE fields are NULL by default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+BEGIN
+SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b rec1.c rec1.d
+NULL NULL NULL NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A cursor%ROWTYPE variable with a ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE := ROW(10,'bbb');
+BEGIN
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A cursor%ROWTYPE variable with an incompatible ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE := ROW(10,'bbb','ccc');
+BEGIN
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A cursor%ROWTYPE variable with a ROW variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 ROW(a INT, b VARCHAR(10)):= ROW(10,'bbb');
+rec2 cur%ROWTYPE := rec1;
+BEGIN
+SELECT rec2.a, rec2.b;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A ROW variable using a cursor%ROWTYPE variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE := ROW(10,'bbb');
+rec2 ROW(a INT, b VARCHAR(10)):= rec1;
+BEGIN
+SELECT rec2.a, rec2.b;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning cursor%ROWTYPE variables with a different column count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+rec2 cur2%ROWTYPE;
+BEGIN
+rec2:=rec1;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+rec2 cur2%ROWTYPE;
+BEGIN
+rec1:=rec2;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 3 column(s)
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning compatible cursor%ROWTYPE variables (equal number of fields)
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+rec2 cur2%ROWTYPE;
+BEGIN
+rec1.a:= 10;
+rec1.b:= 'bbb';
+rec2:=rec1;
+SELECT rec2.x, rec2.y;
+END;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between incompatible cursor%ROWTYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+rec2 ROW(x INT,y INT,z INT);
+BEGIN
+rec2.x:= 10;
+rec2.y:= 20;
+rec2.z:= 30;
+rec1:= rec2;
+END;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between compatible cursor%ROWTYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+rec2 ROW(x INT,y INT);
+BEGIN
+rec2.x:= 10;
+rec2.y:= 20;
+rec1:= rec2;
+SELECT rec1.a, rec1.b;
+rec1.a:= 11;
+rec1.b:= 21;
+rec2:= rec1;
+SELECT rec2.x, rec2.y;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+rec2.x rec2.y
+11 21
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning cursor%ROWTYPE from a ROW expression
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+BEGIN
+rec1:= ROW(10,20);
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor%ROWTYPE variable with a wrong field count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+DECLARE
+rec2 cur2%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec2;
+CLOSE cur1;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Incorrect number of FETCH variables
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor%ROWTYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+OPEN cur;
+LOOP
+FETCH cur INTO rec;
+EXIT WHEN cur%NOTFOUND;
+SELECT rec.a, rec.b, rec.c, rec.d;
+INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+END LOOP;
+CLOSE cur;
+END;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d
+10 bb1 11111.1 12.31
+rec.a rec.b rec.c rec.d
+20 bb2 22222.2 12.32
+rec.a rec.b rec.c rec.d
+30 bb3 33333.3 12.33
+SELECT * FROM t2;
+a b c d
+10 bb1 11111.1 12.31
+20 bb2 22222.2 12.32
+30 bb3 33333.3 12.33
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor%ROWTYPE variable, cur%ROWTYPE declared inside the LOOP
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+CREATE PROCEDURE p1()
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+OPEN cur;
+LOOP
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+FETCH cur INTO rec;
+EXIT WHEN cur%NOTFOUND;
+SELECT rec.a, rec.b, rec.c, rec.d;
+INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+END;
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d
+10 bb1 11111.1 12.31
+rec.a rec.b rec.c rec.d
+20 bb2 22222.2 12.32
+rec.a rec.b rec.c rec.d
+30 bb3 33333.3 12.33
+SELECT * FROM t2;
+a b c d
+10 bb1 11111.1 12.31
+20 bb2 22222.2 12.32
+30 bb3 33333.3 12.33
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor%ROWTYPE variable with different column names
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+DECLARE
+rec2 cur2%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.x, rec2.y;
+CLOSE cur1;
+END;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a cursor%ROWTYPE variable, with truncation
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+DECLARE
+rec2 cur2%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.a, rec2.b;
+CLOSE cur1;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 11
+Warnings:
+Warning 1265 Data truncated for column 'b' at row 1
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# cursor%ROWTYPE variables are not allowed in LIMIT
+#
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+CREATE PROCEDURE p1()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE:=(1,2);
+BEGIN
+SELECT * FROM t1 LIMIT rec1.a;
+END;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+DROP TABLE t1;
+#
+# cursor%ROWTYPE variable fields as OUT parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a OUT INT,b OUT VARCHAR(10))
+AS
+BEGIN
+a:=10;
+b:='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+BEGIN
+CALL p1(rec1.a, rec1.b);
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire cursor%ROWTYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur%ROWTYPE:= ROW(10,'bb');
+BEGIN
+CALL p1(rec1);
+END;
+END;
+$$
+CALL p2();
+a.a a.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire cursor%ROWTYPE variable as an OUT parameter
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a OUT ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+a:= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec1 cur%ROWTYPE;
+BEGIN
+CALL p1(rec1);
+SELECT rec1.a, rec1.b;
+END;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Assigning a cursor%ROWTYPE field to an OUT parameter
+#
+CREATE PROCEDURE p1 (res IN OUT INTEGER)
+AS
+a INT:=10;
+CURSOR cur1 IS SELECT a FROM DUAL;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+res:=rec1.a;
+END;
+END;
+$$
+CALL p1(@res);
+SELECT @res;
+@res
+10
+SET @res=NULL;
+DROP PROCEDURE p1;
+#
+# Testing Item_splocal_row_field_by_name::print
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+EXPLAIN EXTENDED SELECT rec.a, rec.b;
+END;
+END;
+$$
+CALL p1();
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select rec.a@0["a"] AS "rec.a",rec.b@0["b"] AS "rec.b"
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Run time error in the cursor statement
+#
+CREATE PROCEDURE p1
+AS
+CURSOR cur1 IS SELECT
+10 AS a,
+CONCAT(_latin1'a' COLLATE latin1_bin,
+_latin1'a' COLLATE latin1_swedish_ci) AS b;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SELECT a,b;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation 'concat_operator_oracle'
+DROP PROCEDURE p1;
+#
+# Non-existing field
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur1%ROWTYPE;
+BEGIN
+SELECT rec.c;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+ALTER TABLE t1 ADD c INT;
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+rec.c
+NULL
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that field names are case insensitive
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE:=ROW(10,'bb');
+BEGIN
+SELECT rec.A, rec.B;
+END;
+END;
+$$
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that cursor%ROWTYPE uses temporary tables vs shadowed real tables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE:=ROW(10,'bb');
+BEGIN
+SELECT rec.A, rec.B;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'A'
+DROP TEMPORARY TABLE t1;
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that the structure of cursor%ROWTYPE variables is determined at the CURSOR instantiation time
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+DECLARE
+rec cur%ROWTYPE; -- This has a column "c"
+ BEGIN
+rec.c:=10;
+END;
+END;
+$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE; -- This does not have a column "c"
+ BEGIN
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+rec.c:=10;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Duplicate field nams in a cursor referenced by %ROWTYPE
+#
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+CREATE PROCEDURE p1 AS
+CURSOR cur IS SELECT * FROM t1, t2;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+SELECT rec.a;
+rec.a:=10;
+END;
+END;
+$$
+CALL p1();
+ERROR 42S21: Duplicate column name 'a'
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# Tricky field names a cursor referenced by %ROWTYPE
+#
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('a');
+CREATE PROCEDURE p1 AS
+CURSOR cur IS SELECT a, CONCAT(a,'a'), CONCAT(a,'ö') FROM t1;
+BEGIN
+DECLARE
+rec cur%ROWTYPE;
+BEGIN
+OPEN cur;
+FETCH cur INTO rec;
+CLOSE cur;
+SELECT rec.a, rec."CONCAT(a,'a')", rec."CONCAT(a,'ö')";
+END;
+END;
+$$
+CALL p1();
+rec.a rec."CONCAT(a,'a')" rec."CONCAT(a,'ö')"
+a aa aö
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SET NAMES latin1;
+#
+# Using definitions recursively (cursor%ROWTYPE variables in another cursor SELECT)
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b1'),(20,'b2'),(30,'b3');
+CREATE PROCEDURE p1 AS
+CURSOR cur1 IS SELECT a,b FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE:=ROW(0,'b0');
+CURSOR cur2 IS SELECT rec1.a AS a, rec1.b AS b FROM t1;
+BEGIN
+DECLARE
+rec2 cur2%ROWTYPE;
+BEGIN
+OPEN cur2;
+LOOP
+FETCH cur2 INTO rec2;
+EXIT WHEN cur2%NOTFOUND;
+SELECT rec2.a, rec2.b;
+END LOOP;
+CLOSE cur2;
+END;
+END;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+0 b0
+rec2.a rec2.b
+0 b0
+rec2.a rec2.b
+0 b0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing queries with auto-generated Items.
+# An instance of Item_func_conv_charset is created during the below SELECT query.
+# We check here that during an implicit cursor OPEN
+# done in sp_instr_cursor_copy_struct::exec_core()
+# all temporary Items are created on a proper memory root and are safely destroyed.
+#
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b VARCHAR(10) CHARACTER SET utf8);
+INSERT INTO t1 VALUES (0xFF, 'a');
+CREATE PROCEDURE p1
+AS
+CURSOR cur1 IS SELECT CONCAT(a,b) AS c FROM t1;
+BEGIN
+DECLARE
+rec1 cur1%ROWTYPE;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec1;
+CLOSE cur1;
+SELECT HEX(rec1.c);
+END;
+END;
+$$
+CALL p1();
+HEX(rec1.c)
+C3BF61
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-10581 sql_mode=ORACLE: Explicit cursor FOR LOOP
+#
+# IN followed by a non-identifier
+CREATE PROCEDURE p1 AS
+CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+FOR rec IN 10
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP
+NULL;
+END LOOP;
+END' at line 6
+# IN followed by a quoted identifier: table.column
+CREATE PROCEDURE p1 AS
+CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+FOR rec IN c1.c2
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP
+NULL;
+END LOOP;
+END' at line 6
+# IN followed by a quoted identifier: .table.column
+CREATE PROCEDURE p1 AS
+CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+FOR rec IN .c1.c2
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP
+NULL;
+END LOOP;
+END' at line 6
+# IN followed by a quoted identifier: schema.table.column
+CREATE PROCEDURE p1 AS
+CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+FOR rec IN c1.c2.c3
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOOP
+NULL;
+END LOOP;
+END' at line 6
+# IN followed by an unknown cursor name
+CREATE PROCEDURE p1 AS
+CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+FOR rec IN c2
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+ERROR 42000: Undefined CURSOR: c2
+# Make sure "rec" shadows other declarations outside the loop
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10, 'b0');
+CREATE PROCEDURE p1 AS
+rec INT:=10;
+CURSOR c1 IS SELECT a,b FROM t1;
+BEGIN
+FOR rec IN c1
+LOOP
+SELECT rec.a;
+END LOOP;
+SELECT rec;
+END;
+$$
+CALL p1;
+rec.a
+10
+rec
+10
+DROP PROCEDURE p1;
+DROP TABLE t1;
+# Make sure "rec" is not visible after END LOOP
+CREATE PROCEDURE p1 AS
+CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+FOR rec IN c1
+LOOP
+NULL;
+END LOOP;
+rec.a:= 10;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'rec'
+# Make sure that duplicate column names are not allowed
+CREATE PROCEDURE p1 AS
+CURSOR cur IS SELECT 'a' AS a, 'A' as a;
+BEGIN
+FOR rec IN cur
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+CALL p1;
+ERROR 42S21: Duplicate column name 'a'
+DROP PROCEDURE p1;
+# A complete working example
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b0');
+INSERT INTO t1 VALUES (11,'b1');
+INSERT INTO t1 VALUES (12,'b2');
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+CREATE PROCEDURE p1 AS
+CURSOR cur IS SELECT a, b FROM t1;
+BEGIN
+FOR rec IN cur
+LOOP
+SELECT rec.a, rec.b;
+INSERT INTO t2 VALUES (rec.a, rec.b);
+rec.a:= rec.a + 1000;
+rec.b:= 'b' || rec.b;
+INSERT INTO t3 VALUES (rec.a, rec.b);
+END LOOP;
+END;
+$$
+CALL p1();
+rec.a rec.b
+10 b0
+rec.a rec.b
+11 b1
+rec.a rec.b
+12 b2
+SELECT * FROM t2;
+a b
+10 b0
+11 b1
+12 b2
+SELECT * FROM t3;
+a b
+1010 bb0
+1011 bb1
+1012 bb2
+DROP PROCEDURE p1;
+DROP TABLE t3;
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-12314 Implicit cursor FOR LOOP for cursors with parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b0');
+INSERT INTO t1 VALUES (11,'b1');
+INSERT INTO t1 VALUES (12,'b2');
+CREATE PROCEDURE p1(pa INT, pb VARCHAR(32)) AS
+CURSOR cur(va INT, vb VARCHAR(32)) IS
+SELECT a, b FROM t1 WHERE a=va AND b=vb;
+BEGIN
+FOR rec IN cur(pa,pb)
+LOOP
+SELECT rec.a, rec.b;
+END LOOP;
+END;
+$$
+CALL p1(10,'B0');
+rec.a rec.b
+10 b0
+CALL p1(11,'B1');
+rec.a rec.b
+11 b1
+CALL p1(12,'B2');
+rec.a rec.b
+12 b2
+CALL p1(12,'non-existing');
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MDEV-12098 sql_mode=ORACLE: Implicit cursor FOR loop
+#
+# Parse error in the cursor SELECT statement
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT a, b FROM)
+LOOP
+SELECT rec.a, rec.b;
+END LOOP;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')
+LOOP
+SELECT rec.a, rec.b;
+END LOOP;
+END' at line 3
+# Make sure "rec" is not visible after END LOOP
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT 'test' AS a)
+LOOP
+NULL;
+END LOOP;
+rec.a:= 10;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'rec'
+# Make sure "rec" is not visible inside the SELECT statement
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT rec)
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+CALL p1;
+ERROR 42S22: Unknown column 'rec' in 'field list'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT rec.a)
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+CALL p1;
+ERROR 42S02: Unknown table 'rec' in field list
+DROP PROCEDURE p1;
+# Totally confusing name mixture
+CREATE TABLE rec (rec INT);
+INSERT INTO rec VALUES (10);
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT rec FROM rec)
+LOOP
+SELECT rec.rec;
+END LOOP;
+END;
+$$
+CALL p1;
+rec.rec
+10
+DROP PROCEDURE p1;
+DROP TABLE rec;
+# Make sure that duplicate column names are not allowed
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT 'a' AS a, 'A' as a)
+LOOP
+NULL;
+END LOOP;
+END;
+$$
+CALL p1;
+ERROR 42S21: Duplicate column name 'a'
+DROP PROCEDURE p1;
+# A complete working example
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b0');
+INSERT INTO t1 VALUES (11,'b1');
+INSERT INTO t1 VALUES (12,'b2');
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec IN (SELECT a, b FROM t1)
+LOOP
+SELECT rec.a, rec.b;
+INSERT INTO t2 VALUES (rec.a, rec.b);
+rec.a:= rec.a + 1000;
+rec.b:= 'b'|| rec.b;
+INSERT INTO t3 VALUES (rec.a, rec.b);
+END LOOP;
+END;
+$$
+CALL p1();
+rec.a rec.b
+10 b0
+rec.a rec.b
+11 b1
+rec.a rec.b
+12 b2
+SELECT * FROM t2;
+a b
+10 b0
+11 b1
+12 b2
+SELECT * FROM t3;
+a b
+1010 bb0
+1011 bb1
+1012 bb2
+DROP PROCEDURE p1;
+DROP TABLE t3;
+DROP TABLE t2;
+DROP TABLE t1;
+# A combination of explicit and implicit cursors
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b1');
+INSERT INTO t1 VALUES (11,'b2');
+INSERT INTO t1 VALUES (12,'b3');
+CREATE PROCEDURE p1 AS
+BEGIN
+FOR rec1 IN (SELECT a, b FROM t1)
+LOOP
+DECLARE
+CURSOR cur2 IS SELECT a+1000 AS a, 'bb'||b AS b FROM t1 WHERE a=rec1.a AND b=rec1.b;
+BEGIN
+SELECT rec1.a, rec1.b;
+FOR rec2 IN cur2
+LOOP
+SELECT rec2.a, rec2.b;
+END LOOP;
+END;
+END LOOP;
+FOR rec1 IN (SELECT a,b FROM t1)
+LOOP
+FOR rec2 IN (SELECT a+2000 AS a,'bbb'||b AS b FROM t1 WHERE a=rec1.a AND b=rec1.b)
+LOOP
+SELECT rec2.a, rec2.b;
+END LOOP;
+END LOOP;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b1
+rec2.a rec2.b
+1010 bbb1
+rec1.a rec1.b
+11 b2
+rec2.a rec2.b
+1011 bbb2
+rec1.a rec1.b
+12 b3
+rec2.a rec2.b
+1012 bbb3
+rec2.a rec2.b
+2010 bbbb1
+rec2.a rec2.b
+2011 bbbb2
+rec2.a rec2.b
+2012 bbbb3
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor.result b/mysql-test/suite/compat/oracle/r/sp-cursor.result
new file mode 100644
index 00000000000..03211509f8b
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-cursor.result
@@ -0,0 +1,951 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
+#
+#
+# Cursor attributes outside of an SP context
+#
+SELECT c%ISOPEN;
+ERROR 42000: Undefined CURSOR: c
+SELECT c%FOUND;
+ERROR 42000: Undefined CURSOR: c
+SELECT c%NOTFOUND;
+ERROR 42000: Undefined CURSOR: c
+SELECT c%ROWCOUNT;
+ERROR 42000: Undefined CURSOR: c
+#
+# Undefinite cursor attributes
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+SELECT c%ISOPEN;
+END;
+$$
+ERROR 42000: Undefined CURSOR: c
+CREATE PROCEDURE p1
+AS
+BEGIN
+SELECT c%ROWCOUNT;
+END;
+$$
+ERROR 42000: Undefined CURSOR: c
+CREATE PROCEDURE p1
+AS
+BEGIN
+SELECT c%FOUND;
+END;
+$$
+ERROR 42000: Undefined CURSOR: c
+CREATE PROCEDURE p1
+AS
+BEGIN
+SELECT c%NOTFOUND;
+END;
+$$
+ERROR 42000: Undefined CURSOR: c
+#
+# Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT
+#
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+SELECT c%ROWCOUNT;
+END;
+$$
+CALL p1;
+ERROR 24000: Cursor is not open
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+SELECT c%FOUND;
+END;
+$$
+CALL p1;
+ERROR 24000: Cursor is not open
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+SELECT c%NOTFOUND;
+END;
+$$
+CALL p1;
+ERROR 24000: Cursor is not open
+DROP PROCEDURE p1;
+#
+# Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT with INVALID_CURSOR exception
+#
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+SELECT c%ROWCOUNT;
+EXCEPTION
+WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
+END;
+$$
+CALL p1;
+c%ROWCOUNT
+msg
+INVALID_CURSOR caught
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+SELECT c%FOUND;
+EXCEPTION
+WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
+END;
+$$
+CALL p1;
+c%FOUND
+msg
+INVALID_CURSOR caught
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+SELECT c%NOTFOUND;
+EXCEPTION
+WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
+END;
+$$
+CALL p1;
+c%NOTFOUND
+msg
+INVALID_CURSOR caught
+DROP PROCEDURE p1;
+#
+# print()
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+EXPLAIN EXTENDED SELECT c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+END;
+$$
+CALL p1();
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select "c"%ISOPEN AS "c%ISOPEN","c"%ROWCOUNT AS "c%ROWCOUNT","c"%FOUND AS "c%FOUND","c"%NOTFOUND AS "c%NOTFOUND"
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Declared data type of the attributes
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+CREATE PROCEDURE p1
+AS
+CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+OPEN c;
+CREATE TABLE t2 AS SELECT c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+CLOSE c;
+END;
+$$
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "c%ISOPEN" int(1) NOT NULL,
+ "c%ROWCOUNT" bigint(21) DEFAULT NULL,
+ "c%FOUND" int(1) DEFAULT NULL,
+ "c%NOTFOUND" int(1) DEFAULT NULL
+)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Core functionality
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (30);
+CREATE PROCEDURE p1
+AS
+a INT:=0;
+CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+SELECT a, c%ISOPEN;
+OPEN c;
+/*
+After OPEN and before FETCH:
+- %ROWCOUNT returns 0
+- %FOUND and %NOTFOUND return NULL
+*/
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+FETCH c INTO a;
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+FETCH c INTO a;
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+FETCH c INTO a;
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+FETCH c INTO a;
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+CLOSE c;
+SELECT a, c%ISOPEN;
+/*
+After reopen and before FETCH:
+- %ROWCOUNT returns 0
+- %FOUND and %NOTFOUND return NULL
+*/
+OPEN c;
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+FETCH c INTO a;
+SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+CLOSE c;
+END;
+$$
+CALL p1();
+a c%ISOPEN
+0 0
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+0 1 0 NULL NULL
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+10 1 1 1 0
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+20 1 2 1 0
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+30 1 3 1 0
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+30 1 3 0 1
+a c%ISOPEN
+30 0
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+30 1 0 NULL NULL
+a c%ISOPEN c%ROWCOUNT c%FOUND c%NOTFOUND
+10 1 1 1 0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# %NOTFOUND as a loop exit condition
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (30);
+CREATE PROCEDURE p1
+AS
+a INT:=0;
+CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+OPEN c;
+LOOP
+FETCH c INTO a;
+EXIT WHEN c%NOTFOUND;
+SELECT a;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1();
+a
+10
+a
+20
+a
+30
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# %FOUND as a loop exit condition
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (30);
+CREATE PROCEDURE p1
+AS
+a INT:=0;
+CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+OPEN c;
+LOOP
+FETCH c INTO a;
+EXIT WHEN NOT c%FOUND;
+SELECT a;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1();
+a
+10
+a
+20
+a
+30
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# End of MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
+#
+#
+# MDEV-10597 Cursors with parameters
+#
+#
+# OPEN with a wrong number of parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a_a INT,a_b VARCHAR)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
+BEGIN
+OPEN c(a_a);
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+DBMS_OUTPUT.PUT_LINE('Fetched a record a='||TO_CHAR(v_a)||' b='||v_b);
+END LOOP;
+CLOSE c;
+END;
+$$
+ERROR 42000: Incorrect parameter count to cursor 'c'
+DROP TABLE t1;
+#
+# Cursor parameters are not visible outside of the cursor
+#
+CREATE PROCEDURE p1(a_a INT)
+AS
+v_a INT;
+CURSOR c (p_a INT) IS SELECT a FROM t1 WHERE a=p_a;
+BEGIN
+OPEN c(a_a);
+p_a:=10;
+END;
+$$
+ERROR HY000: Unknown system variable 'p_a'
+CREATE PROCEDURE p1(a_a INT)
+AS
+v_a INT;
+CURSOR c (p_a INT) IS SELECT a FROM t1 WHERE a=p_a;
+BEGIN
+p_a:=10;
+OPEN c(a_a);
+END;
+$$
+ERROR HY000: Unknown system variable 'p_a'
+#
+# Cursor parameter shadowing a local variable
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE PROCEDURE p1(a INT)
+AS
+v_a INT:=NULL;
+p_a INT:=NULL;
+CURSOR c (p_a VARCHAR2) IS SELECT a FROM t1 WHERE p_a IS NOT NULL;
+BEGIN
+OPEN c(a);
+FETCH c INTO v_a;
+IF c%NOTFOUND THEN
+BEGIN
+SELECT 'No records found' AS msg;
+RETURN;
+END;
+END IF;
+CLOSE c;
+SELECT 'Fetched a record a='||v_a AS msg;
+INSERT INTO t1 VALUES (v_a);
+END;
+$$
+CALL p1(1);
+msg
+Fetched a record a=1
+SELECT * FROM t1;
+a
+1
+1
+CALL p1(NULL);
+msg
+No records found
+SELECT * FROM t1;
+a
+1
+1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Parameters in SELECT list
+#
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR c (p_a INT, p_b VARCHAR) IS SELECT p_a,p_b FROM DUAL;
+BEGIN
+FOR i IN 0..1
+LOOP
+OPEN c(a_a + i,a_b);
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+SELECT 'Fetched a record a=' || v_a || ' b=' || v_b AS msg;
+END LOOP;
+CLOSE c;
+END LOOP;
+END;
+$$
+CALL p1(1,'b1');
+msg
+Fetched a record a=1 b=b1
+msg
+Fetched a record a=2 b=b1
+DROP PROCEDURE p1;
+#
+# Parameters in SELECT list + UNION
+#
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR c (p_a INT, p_b VARCHAR) IS
+SELECT p_a,p_b FROM DUAL
+UNION ALL
+SELECT p_a+1,p_b||'b' FROM DUAL;
+BEGIN
+OPEN c(a_a,a_b);
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+SELECT 'Fetched a record a=' || v_a || ' b=' || v_b AS msg;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1(1,'b1');
+msg
+Fetched a record a=1 b=b1
+msg
+Fetched a record a=2 b=b1b
+DROP PROCEDURE p1;
+#
+# Parameters in SELECT list + type conversion + warnings
+#
+CREATE PROCEDURE p1(a_a VARCHAR)
+AS
+v_a INT;
+CURSOR c (p_a INT) IS SELECT p_a FROM DUAL;
+BEGIN
+OPEN c(a_a);
+LOOP
+FETCH c INTO v_a;
+EXIT WHEN c%NOTFOUND;
+SELECT 'Fetched a record a=' || v_a AS msg;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('1b');
+msg
+Fetched a record a=1
+Warnings:
+Warning 1265 Data truncated for column 'p_a' at row 1
+CALL p1('b1');
+msg
+Fetched a record a=0
+Warnings:
+Warning 1366 Incorrect integer value: 'b1' for column 'p_a' at row 1
+DROP PROCEDURE p1;
+#
+# One parameter in SELECT list + subselect
+#
+CREATE PROCEDURE p1(a_a VARCHAR)
+AS
+v_a VARCHAR(10);
+CURSOR c (p_a VARCHAR) IS
+SELECT p_a FROM DUAL UNION SELECT REVERSE(p_a) FROM DUAL;
+BEGIN
+OPEN c((SELECT a_a));
+LOOP
+FETCH c INTO v_a;
+EXIT WHEN c%NOTFOUND;
+SELECT v_a;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('ab');
+v_a
+ab
+v_a
+ba
+DROP PROCEDURE p1;
+#
+# Two parameters in SELECT list + subselect
+#
+SET sql_mode=ORACLE;
+CREATE PROCEDURE p1()
+AS
+v_a VARCHAR(10);
+v_b VARCHAR(20);
+CURSOR c (p_a VARCHAR, p_b VARCHAR) IS
+SELECT p_a, p_b FROM DUAL
+UNION
+SELECT p_b, p_a FROM DUAL;
+BEGIN
+OPEN c((SELECT 'aaa'),(SELECT 'bbb'));
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+SELECT v_a, v_b;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1();
+v_a v_b
+aaa bbb
+v_a v_b
+bbb aaa
+DROP PROCEDURE p1;
+#
+# Two parameters in SELECT list + two parameters in WHERE + subselects
+#
+SET sql_mode=ORACLE;
+CREATE PROCEDURE p1(a_a VARCHAR, a_b VARCHAR)
+AS
+v_a VARCHAR(10);
+v_b VARCHAR(20);
+CURSOR c (value_a VARCHAR, value_b VARCHAR,
+pattern_a VARCHAR, pattern_b VARCHAR) IS
+SELECT value_a, value_b FROM DUAL WHERE value_a LIKE pattern_a
+UNION
+SELECT value_b, value_a FROM DUAL WHERE value_b LIKE pattern_b;
+BEGIN
+OPEN c((SELECT 'aaa'),(SELECT 'bbb'),(SELECT a_a),(SELECT a_b));
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+SELECT v_a, v_b;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('%','%');
+v_a v_b
+aaa bbb
+v_a v_b
+bbb aaa
+CALL p1('aaa','xxx');
+v_a v_b
+aaa bbb
+CALL p1('xxx','bbb');
+v_a v_b
+bbb aaa
+CALL p1('xxx','xxx');
+DROP PROCEDURE p1;
+#
+# Parameters in SELECT list + stored function
+#
+CREATE FUNCTION f1 (a VARCHAR) RETURN VARCHAR
+AS
+BEGIN
+RETURN a || 'y';
+END;
+$$
+CREATE PROCEDURE p1(a_a VARCHAR)
+AS
+v_a VARCHAR(10);
+v_b VARCHAR(10);
+CURSOR c (p_sel_a VARCHAR, p_cmp_a VARCHAR) IS
+SELECT p_sel_a, p_cmp_a FROM DUAL;
+BEGIN
+OPEN c(f1(a_a), f1(a_a));
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+SELECT v_a;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1('x');
+v_a
+xy
+CALL p1(f1(COALESCE(NULL, f1('x'))));
+v_a
+xyyy
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+#
+# One parameter in WHERE clause
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+CREATE PROCEDURE p1(a_a INT)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR c (p_a INT) IS SELECT a,b FROM t1 WHERE a=p_a;
+BEGIN
+OPEN c(a_a);
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+INSERT INTO t2 VALUES (v_a,v_b);
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1(1);
+SELECT * FROM t2;
+a b
+1 11
+1 12
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+#
+# Two parameters in WHERE clause
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR c (p_a INT, p_b VARCHAR) IS SELECT a,b FROM t1 WHERE a=p_a AND b=p_b;
+BEGIN
+OPEN c(a_a, a_b);
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+INSERT INTO t2 VALUES (v_a,v_b);
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1(1,'11');
+SELECT * FROM t2;
+a b
+1 11
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+#
+# Parameters in WHERE and HAVING clauses
+#
+CREATE TABLE t1 (name VARCHAR(10), value INT);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bot',1);
+CREATE PROCEDURE p1 (arg_name_limit VARCHAR, arg_total_limit INT)
+AS
+v_name VARCHAR(10);
+v_total INT;
+-- +0 is needed to work around the bug MDEV-11081
+CURSOR c(p_v INT) IS
+SELECT name, SUM(value + p_v) + 0 AS total FROM t1
+WHERE name LIKE arg_name_limit
+GROUP BY name HAVING total>=arg_total_limit;
+BEGIN
+FOR i IN 0..1
+LOOP
+OPEN c(i);
+LOOP
+FETCH c INTO v_name, v_total;
+EXIT WHEN c%NOTFOUND;
+SELECT v_name, v_total;
+END LOOP;
+CLOSE c;
+END LOOP;
+END;
+$$
+CALL p1('%', 2);
+v_name v_total
+bin 2
+v_name v_total
+but 3
+v_name v_total
+bin 4
+v_name v_total
+bot 2
+v_name v_total
+but 6
+CALL p1('b_t', 0);
+v_name v_total
+bot 1
+v_name v_total
+but 3
+v_name v_total
+bot 2
+v_name v_total
+but 6
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# One parameter in LIMIT clause
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'b1');
+INSERT INTO t1 VALUES (2,'b2');
+INSERT INTO t1 VALUES (3,'b3');
+INSERT INTO t1 VALUES (4,'b4');
+INSERT INTO t1 VALUES (5,'b5');
+INSERT INTO t1 VALUES (6,'b6');
+CREATE PROCEDURE p1(a_a INT)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR c (p_a INT) IS SELECT a,b FROM t1 ORDER BY a LIMIT p_a;
+BEGIN
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+OPEN c(a_a);
+LOOP
+FETCH c INTO v_a, v_b;
+EXIT WHEN c%NOTFOUND;
+INSERT INTO t2 VALUES (v_a,v_b);
+END LOOP;
+CLOSE c;
+SELECT * FROM t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1(1);
+a b
+1 b1
+CALL p1(3);
+a b
+1 b1
+2 b2
+3 b3
+CALL p1(6);
+a b
+1 b1
+2 b2
+3 b3
+4 b4
+5 b5
+6 b6
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-10597 Cursors with parameters
+#
+#
+# MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'A');
+CREATE PROCEDURE p1(a INT,b VARCHAR)
+AS
+CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
+BEGIN
+OPEN c(a+, b);
+LOOP
+FETCH c INTO a, b;
+EXIT WHEN c%NOTFOUND;
+SELECT a, b;
+END LOOP;
+CLOSE c;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' b);
+LOOP
+FETCH c INTO a, b;
+EXIT WHEN c%NOTFOUND;
+SELECT a, b;
+END LOOP;
+CLOSE ' at line 5
+DROP TABLE t1;
+#
+# MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
+INSERT INTO t1 VALUES (1,'b1','2001-01-01 10:20:30.123');
+INSERT INTO t1 VALUES (2,'b2','2001-01-02 10:20:30.123');
+CREATE TABLE t2 LIKE t1;
+CREATE PROCEDURE p1()
+AS
+v_a t1.a%TYPE;
+v_b t1.b%TYPE;
+v_c t1.c%TYPE;
+CURSOR c IS SELECT a,b,c FROM t1;
+BEGIN
+OPEN c;
+LOOP
+FETCH c INTO v_a, v_b, v_c;
+EXIT WHEN c%NOTFOUND;
+INSERT INTO t2 (a,b,c) VALUES (v_a, v_b, v_c);
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1();
+SELECT * FROM t2;
+a b c
+1 b1 2001-01-01 10:20:30.123
+2 b2 2001-01-02 10:20:30.123
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-12007 Allow ROW variables as a cursor FETCH target
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+CREATE PROCEDURE p1 AS
+rec ROW(a INT, b VARCHAR(32));
+CURSOR c IS SELECT a,b FROM t1;
+BEGIN
+OPEN c;
+LOOP
+FETCH c INTO rec;
+EXIT WHEN c%NOTFOUND;
+SELECT ('rec=(' || rec.a ||','|| rec.b||')') AS c;
+END LOOP;
+CLOSE c;
+END;
+$$
+CALL p1();
+c
+rec=(10,b10)
+c
+rec=(20,b20)
+c
+rec=(30,b30)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-12441 Variables declared after cursors with parameters lose values
+#
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 INT:=101;
+BEGIN
+OPEN cur(10,11);
+CLOSE cur;
+SELECT x0, x1;
+END;
+$$
+CALL p1();
+x0 x1
+100 101
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 t1.a%TYPE:=101;
+BEGIN
+OPEN cur(10,11);
+CLOSE cur;
+SELECT x0, x1;
+END;
+$$
+CALL p1();
+x0 x1
+100 101
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+x1 ROW(a INT,b INT):=ROW(101,102);
+BEGIN
+OPEN cur(10,11);
+CLOSE cur;
+SELECT x0, x1.a, x1.b;
+END;
+$$
+CALL p1();
+x0 x1.a x1.b
+100 101 102
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'Tbl-t1.b0');
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT a,b FROM t1;
+x1 t1%ROWTYPE:=ROW(101,'Var-x1.b0');
+BEGIN
+SELECT x0, x1.a, x1.b;
+OPEN cur(10,11);
+FETCH cur INTO x1;
+CLOSE cur;
+SELECT x0, x1.a, x1.b;
+END;
+$$
+CALL p1();
+x0 x1.a x1.b
+100 101 Var-x1.b0
+x0 x1.a x1.b
+100 10 Tbl-t1.b0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'Tbl-t1.b0');
+CREATE PROCEDURE p1() AS
+x0 INT:=100;
+CURSOR cur(cp1 INT, cp2 INT) IS SELECT a,b FROM t1;
+x1 cur%ROWTYPE:=ROW(101,'Var-x1.b0');
+BEGIN
+SELECT x0, x1.a, x1.b;
+OPEN cur(10,11);
+FETCH cur INTO x1;
+CLOSE cur;
+SELECT x0, x1.a, x1.b;
+END;
+$$
+CALL p1();
+x0 x1.a x1.b
+100 101 Var-x1.b0
+x0 x1.a x1.b
+100 10 Tbl-t1.b0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+DECLARE
+CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+OPEN c;
+SELECT
+c%ISOPEN,
+c%NOTFOUND,
+c%FOUND,
+c%ROWCOUNT;
+CLOSE c;
+END;
+$$
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def c%ISOPEN 3 1 1 N 32897 0 63
+def c%NOTFOUND 3 1 0 Y 32896 0 63
+def c%FOUND 3 1 0 Y 32896 0 63
+def c%ROWCOUNT 8 21 1 Y 32896 0 63
+c%ISOPEN c%NOTFOUND c%FOUND c%ROWCOUNT
+1 NULL NULL 0
diff --git a/mysql-test/suite/compat/oracle/r/sp-goto.result b/mysql-test/suite/compat/oracle/r/sp-goto.result
new file mode 100644
index 00000000000..259be7a34e6
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-goto.result
@@ -0,0 +1,834 @@
+set sql_mode=oracle;
+#
+# MDEV-10697 sql_mode=ORACLE: GOTO statement
+#
+# matrice of tests in procedure
+# |--------------------------------------------------------
+# | | Same | Outside | to sub | No |
+# | | block | one block | block | matching |
+# | | | | | label |
+# |--------------------------------------------------------
+# | Forward jump | F1 | F3 | F5 | F7 |
+# |--------------------------------------------------------
+# | Backward jump | F2 | F4 | F6 | F8 |
+# |--------------------------------------------------------
+# Jump from handler to outside handling code block : F9
+# Jump from handler to handling code block : F10 (forbidden)
+# Jump inside handler : F21
+# Jump between handler : F22 (forbidden)
+# Jump from cascaded block with handler : F11
+# Duplicate label in same block : F12 (forbidden)
+# Duplicate label in different block : F13
+# Jump outside unlabeled block : F14
+# Jump inside/outside labeled block : F15
+# Jump from if / else : F16
+# Jump with cursors : F17
+# Jump outside case : F18
+# Jump inside/outside case block : F19
+# Jump outside labeled loop : F20
+# Jump (continue) labeled loop : F23
+# Two consecutive label : P24
+# Two consecutive label (backward and forward jump) : P25
+# Two consecutive label, continue to wrong label : P26
+# Consecutive goto label and block label : P27
+# Test in function
+# backward jump : func1
+# forward jump : func2
+# Test in trigger
+# forward jump : trg1
+#
+# Forward jump in same block
+#
+CREATE or replace procedure f1(p2 IN OUT VARCHAR)
+AS
+BEGIN
+p2:='a';
+goto lab1;
+<<lab1>>
+goto lab2;
+p2:='b';
+<<lab2>>
+return ;
+END;
+$$
+call f1(@wp1);
+select 'f1',@wp1;
+f1 @wp1
+f1 a
+DROP PROCEDURE f1;
+#
+# Backward jump in same block
+#
+CREATE or replace procedure f2(p2 IN OUT VARCHAR)
+AS
+BEGIN
+p2:='a';
+<<lab1>>
+if (p2='b') then
+return ;
+end if;
+p2:='b';
+goto lab1;
+END;
+$$
+call f2(@wp1);
+select 'f2',@wp1;
+f2 @wp1
+f2 b
+DROP PROCEDURE f2;
+#
+# Forward jump outside one block
+#
+CREATE or replace procedure f3(p2 IN OUT VARCHAR)
+AS
+BEGIN
+p2:='a';
+if (p2='a') then
+goto lab1;
+end if;
+p2:='c';
+<<lab1>>
+return ;
+END;
+$$
+call f3(@wp1);
+select 'f3',@wp1;
+f3 @wp1
+f3 a
+DROP PROCEDURE f3;
+#
+# Backward jump outside one block
+#
+CREATE or replace procedure f4(p2 IN OUT VARCHAR)
+AS
+BEGIN
+p2:='a';
+<<lab1>>
+if (p2='a') then
+p2:=p2||'b';
+goto lab1;
+end if;
+if (p2='ab') then
+p2:=p2||'c';
+end if;
+return ;
+END;
+$$
+call f4(@wp1);
+select 'f4',@wp1;
+f4 @wp1
+f4 abc
+DROP PROCEDURE f4;
+#
+# Forward jump inside sub block
+CREATE or replace procedure f5(p2 IN OUT VARCHAR)
+AS
+BEGIN
+p2:='a';
+goto lab5 ;
+if (p2='a') then
+<<lab5>>
+p2:=p2||'b';
+end if;
+return ;
+END;
+$$
+ERROR 42000: GOTO with no matching label: lab5
+#
+# Backward jump inside sub block
+CREATE or replace procedure f6(p2 IN OUT VARCHAR)
+AS
+BEGIN
+p2:='a';
+if (p2='a') then
+<<lab6>>
+p2:=p2||'b';
+return ;
+end if;
+goto lab6 ;
+END;
+$$
+ERROR 42000: GOTO with no matching label: lab6
+#
+# Backward jump - missing label
+CREATE or replace procedure f7(p2 IN OUT VARCHAR)
+AS
+BEGIN
+<<lab>>
+goto lab7 ;
+return ;
+END;
+$$
+ERROR 42000: GOTO with no matching label: lab7
+#
+# Forward jump - missing label
+CREATE or replace procedure f8(p2 IN OUT VARCHAR)
+AS
+BEGIN
+goto lab8 ;
+<<lab>>
+return ;
+END;
+$$
+ERROR 42000: GOTO with no matching label: lab8
+#
+# Jump from handler to procedure code
+#
+CREATE or replace procedure f9(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+<<lab9>>
+if lim=-1 then
+res:=res||' -- goto end limit -1 --';
+goto lab9_end;
+end if;
+begin
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+begin
+res:=res||'--- too_many_rows cought ---';
+lim:=0;
+goto lab9;
+end;
+WHEN NO_DATA_FOUND THEN
+begin
+res:=res||'--- no_data_found cought ---';
+lim:=-1;
+goto lab9;
+end;
+end;
+res:=res||'error';
+<<lab9_end>>
+return ;
+END;
+$$
+SET @res='';
+CALL f9(2, @res);
+SELECT 'f9',@res;
+f9 @res
+f9 --- too_many_rows cought ------ no_data_found cought --- -- goto end limit -1 --
+CALL f9(0, @res);
+SELECT 'f9',@res;
+f9 @res
+f9 --- no_data_found cought --- -- goto end limit -1 --
+DROP PROCEDURE f9;
+#
+# Jump from handler to handling bloc
+CREATE or replace procedure f10(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+begin
+<<lab10>>
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+begin
+res:='--- too_many_rows cought ---';
+goto lab10;
+end;
+WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought ---';
+end;
+return ;
+END;
+$$
+ERROR 42000: GOTO with no matching label: lab10
+#
+# Jump from cascaded block with handler
+#
+CREATE or replace procedure f11(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+<<lab11a>>
+begin
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+begin
+res:=res||'--- too_many_rows cought 1 ---';
+goto lab11b;
+end;
+WHEN NO_DATA_FOUND THEN
+begin
+res:=res||'--- no_data_found cought 1 ---';
+lim:=2;
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+begin
+res:=res||'--- too_many_rows cought 2 ---';
+goto lab11a;
+end;
+WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought 2 ---';
+end;
+end;
+set res:=res||' error ';
+<<lab11b>>
+return ;
+END;
+$$
+SET @res='';
+CALL f11(0, @res);
+SELECT 'f11',@res;
+f11 @res
+f11 --- no_data_found cought 1 ------ too_many_rows cought 2 ------ too_many_rows cought 1 ---
+DROP PROCEDURE f11;
+#
+# Jump inside handler
+#
+CREATE or replace procedure f21(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+begin
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+begin
+<<retry>>
+lim:=lim-1;
+loop
+begin
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+begin
+lim:=lim-1;
+goto retry;
+end;
+end;
+exit ;
+end loop;
+end;
+end;
+res:=lim;
+return ;
+END;
+$$
+SET @res='';
+CALL f21(10, @res);
+SELECT 'f21',@res;
+f21 @res
+f21 1
+drop procedure f21;
+#
+# Jump beetween handler
+CREATE or replace procedure f22(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+res:='ok';
+begin
+SELECT a INTO a FROM information_schema.tables LIMIT lim;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN
+goto nodata ;
+WHEN NO_DATA_FOUND THEN
+begin
+<<nodata>>
+res:='error';
+end;
+end;
+return ;
+END;
+$$
+ERROR 42000: GOTO with no matching label: nodata
+#
+# Duplicate label in same bloc
+CREATE or replace procedure f12(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+<<lab12>>
+res:='error';
+<<lab12>>
+return ;
+END;
+$$
+ERROR 42000: Redefining label lab12
+#
+# Duplicate label in different block
+#
+CREATE or replace procedure f13(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+a:=0;
+<<lab13>>
+a:=a+1;
+begin
+<<lab13>>
+a:=a+1;
+if (a<10) then
+goto lab13;
+end if;
+end;
+res:=a;
+if (a=10) then
+goto lab13;
+end if;
+return ;
+END;
+$$
+SET @res='';
+CALL f13(0, @res);
+SELECT 'f13',@res;
+f13 @res
+f13 12
+DROP PROCEDURE f13;
+#
+# Jump outside unlabeled block
+#
+CREATE or replace procedure f14(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+a:=0;
+loop
+a:=a+1;
+if (a<10) then
+continue;
+end if;
+if (a>=lim) then
+goto lab14;
+end if;
+if (a>=20) then
+exit;
+end if;
+end loop;
+<<lab14>>
+res:=a;
+return ;
+END;
+$$
+SET @res='';
+CALL f14(15, @res);
+SELECT 'f14',@res;
+f14 @res
+f14 15
+CALL f14(8, @res);
+SELECT 'f14',@res;
+f14 @res
+f14 10
+CALL f14(25, @res);
+SELECT 'f14',@res;
+f14 @res
+f14 20
+DROP PROCEDURE f14;
+#
+# Jump inside/outside labeled block
+#
+CREATE or replace procedure f15(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+a:=0;
+<<looplabel>> loop
+<<beginlooplabel>>
+a:=a+1;
+if (a<10) then
+continue looplabel;
+end if;
+if (a>=lim) then
+goto lab15;
+end if;
+if (a>=20) then
+exit looplabel;
+end if;
+goto beginlooplabel;
+end loop;
+<<lab15>>
+res:=a;
+return ;
+END;
+$$
+SET @res='';
+CALL f15(15, @res);
+SELECT 'f15',@res;
+f15 @res
+f15 15
+CALL f15(8, @res);
+SELECT 'f15',@res;
+f15 @res
+f15 10
+CALL f15(25, @res);
+SELECT 'f15',@res;
+f15 @res
+f15 20
+DROP PROCEDURE f15;
+#
+# Jump from if / else
+#
+CREATE or replace procedure f16(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+if (lim<10) then
+goto lab16_1;
+else
+goto lab16_2;
+end if;
+<<lab16_1>>
+res:='if lab16_1';
+goto lab16_3;
+<<lab16_2>>
+res:='else lab16_2';
+goto lab16_3;
+res:='error lab16_3';
+<<lab16_3>>
+return ;
+END;
+$$
+SET @res='';
+CALL f16(15, @res);
+SELECT 'f16',@res;
+f16 @res
+f16 else lab16_2
+CALL f16(8, @res);
+SELECT 'f16',@res;
+f16 @res
+f16 if lab16_1
+DROP PROCEDURE f16;
+#
+# Jump with cursors
+#
+CREATE or replace procedure f17(lim INT, res OUT VARCHAR)
+AS
+v_a INT;
+v_b VARCHAR(10);
+CURSOR cur1 IS SELECT 1 FROM dual where 1=2;
+BEGIN
+OPEN cur1;
+LOOP
+FETCH cur1 INTO v_a;
+EXIT WHEN cur1%NOTFOUND;
+END LOOP;
+CLOSE cur1;
+<<lab17>>
+lim:=lim-1;
+begin
+declare
+CURSOR cur1 IS SELECT 1 FROM dual;
+CURSOR cur2 IS SELECT 1 FROM dual where 1=2;
+begin
+LOOP
+OPEN cur1;
+FETCH cur1 INTO v_a;
+EXIT WHEN cur1%NOTFOUND;
+res:=res||'-'||lim ;
+close cur1;
+if (lim>0) then
+goto lab17;
+else
+goto lab17_end;
+end if;
+END LOOP;
+end;
+<<lab17_end>>
+null;
+end;
+END;
+$$
+SET @res='';
+CALL f17(5, @res);
+SELECT 'f17',@res;
+f17 @res
+f17 -4-3-2-1-0
+DROP PROCEDURE f17;
+#
+# Jump outside case
+#
+CREATE or replace procedure f18(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+case lim
+when 1 then
+res:='case branch 18_1';
+goto lab18_1;
+res:='error';
+when 2 then
+res:='case branch 18_2';
+goto lab18_2;
+res:='error';
+else
+res:='default branch 18';
+end case;
+<<lab18_1>>
+null;
+<<lab18_2>>
+return ;
+END;
+$$
+SET @res='';
+CALL f18(0, @res);
+SELECT 'f18',@res;
+f18 @res
+f18 default branch 18
+CALL f18(1, @res);
+SELECT 'f18',@res;
+f18 @res
+f18 case branch 18_1
+CALL f18(2, @res);
+SELECT 'f18',@res;
+f18 @res
+f18 case branch 18_2
+DROP PROCEDURE f18;
+#
+# Jump inside/outside case block
+#
+CREATE or replace procedure f19(lim INT, res OUT VARCHAR)
+AS
+a INT;
+BEGIN
+a:=1;
+case lim
+when 1 then
+<<lab19_0>>
+a:=a+1;
+if (a<10) then
+goto lab19_0;
+else
+goto lab19_1;
+end if;
+res:='case branch 19_1';
+else
+res:='default branch 18';
+end case;
+goto lab19_end;
+<<lab19_1>>
+res:=a;
+<<lab19_end>>
+return ;
+END;
+$$
+SET @res='';
+CALL f19(1, @res);
+SELECT 'f19',@res;
+f19 @res
+f19 10
+DROP PROCEDURE f19;
+#
+# Jump outside labeled loop
+#
+CREATE OR REPLACE PROCEDURE f20(res OUT VARCHAR)
+AS
+a INT := 1;
+BEGIN
+<<lab>>
+FOR i IN a..10 LOOP
+IF i = 5 THEN
+a:= a+1;
+goto lab;
+END IF;
+END LOOP;
+res:=a;
+END;
+$$
+CALL f20(@res);
+SELECT 'f20',@res;
+f20 @res
+f20 6
+DROP PROCEDURE f20;
+#
+# Jump (continue) labeled loop
+#
+CREATE OR REPLACE PROCEDURE f23(res OUT VARCHAR)
+AS
+a INT := 1;
+BEGIN
+<<lab>>
+FOR i IN a..10 LOOP
+IF i = 5 THEN
+a:= a+1;
+continue lab;
+END IF;
+END LOOP;
+res:=a;
+END;
+$$
+CALL f23(@res);
+SELECT 'f23',@res;
+f23 @res
+f23 2
+DROP PROCEDURE f23;
+#
+# Two consecutive label (backward jump)
+#
+CREATE OR REPLACE PROCEDURE p24(action IN INT, res OUT varchar) AS
+a integer;
+BEGIN
+<<lab1>>
+<<lab2>>
+if (action = 1) then
+res:=res||' '||action;
+action:=2;
+goto lab1;
+end if;
+if (action = 2) then
+res:=res||' '||action;
+action:=3;
+goto lab2;
+end if;
+END;
+$$
+call p24(1,@res);
+select 'p24',@res;
+p24 @res
+p24 1 2
+DROP PROCEDURE p24;
+#
+# Two consecutive label (backward and forward jump)
+#
+CREATE OR REPLACE PROCEDURE p25(action IN INT, res OUT varchar) AS
+a integer;
+BEGIN
+if (action = 1) then
+res:=res||' '||action;
+action:=2;
+goto lab2;
+end if;
+goto lab_end;
+<<lab1>>
+<<lab2>>
+res:=res||' '||action;
+if (action = 2) then
+res:=res||' '||action;
+action:=3;
+goto lab1;
+end if;
+<<lab_end>>
+null;
+END;
+$$
+call p25(1,@res);
+select 'p25',@res;
+p25 @res
+p25 1 2 2 3
+DROP PROCEDURE p25;
+#
+# Two consecutive label, continue to wrong label
+CREATE OR REPLACE PROCEDURE p26(action IN INT, res OUT varchar) AS
+BEGIN
+<<lab1>>
+<<lab2>>
+FOR i IN 1..10 LOOP
+continue lab1;
+END LOOP;
+END;
+$$
+ERROR 42000: CONTINUE with no matching label: lab1
+#
+# Consecutive goto label and block label
+#
+CREATE OR REPLACE PROCEDURE p27(action IN INT, res OUT varchar) AS
+BEGIN
+res:='';
+<<lab1>>
+<<lab2>>
+FOR i IN 1..10 LOOP
+if (action = 1) then
+res:=res||' '||action||'-'||i;
+action:=2;
+continue lab2;
+end if;
+if (action = 2) then
+res:=res||' '||action||'-'||i;
+action:='3';
+goto lab2;
+end if;
+if (action = 3) then
+res:=res||' '||action||'-'||i;
+action:='4';
+goto lab1;
+end if;
+if (action = 4) then
+res:=res||' '||action||'-'||i;
+exit lab2;
+end if;
+END LOOP;
+END;
+$$
+call p27(1,@res);
+select 'p27',@res;
+p27 @res
+p27 1-1 2-2 3-1 4-1
+DROP PROCEDURE p27;
+# ----------------------
+# -- TEST IN FUNCTION --
+# ----------------------
+#
+# FUNCTION : Backward jump
+#
+CREATE or replace function func1()
+return varchar
+AS
+p2 varchar(10);
+BEGIN
+p2:='a';
+<<lab1>>
+if (p2='a') then
+p2:=p2||'b';
+goto lab1;
+end if;
+if (p2='ab') then
+p2:=p2||'c';
+end if;
+return p2;
+END;
+$$
+select 'func1',func1();
+func1 func1()
+func1 abc
+DROP function func1;
+#
+# FUNCTION : forward jump
+#
+CREATE or replace function func2()
+return varchar
+AS
+p2 varchar(10);
+BEGIN
+p2:='a';
+if (p2='a') then
+goto lab1;
+end if;
+p2:='b';
+<<lab1>>
+return p2;
+END;
+$$
+select 'func2',func2();
+func2 func2()
+func2 a
+DROP function func2;
+# ---------------------
+# -- TEST IN TRIGGER --
+# ---------------------
+#
+# TRIGGER : forward jump
+#
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+IF :NEW.a IS NULL
+THEN
+:NEW.a:= 15;
+goto end_trg;
+END IF;
+:NEW.a:= 10;
+<<end_trg>>
+null;
+END;
+$$
+insert into t1 values (1);
+insert into t1 values (null);
+SELECT * FROM t1;
+a
+10
+15
+DROP TRIGGER trg1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-param.result b/mysql-test/suite/compat/oracle/r/sp-param.result
new file mode 100644
index 00000000000..4f4585c4570
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-param.result
@@ -0,0 +1,132 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10596 Allow VARCHAR and VARCHAR2 without length as a data type of routine parameters and in RETURN clause
+#
+CREATE FUNCTION f1(param CHAR) RETURN CHAR AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param CHAR) RETURN varchar(2000) CHARSET latin1
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',2000)));;
+LENGTH(f1(REPEAT('a',2000)))
+2000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" text DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param NCHAR) RETURN NCHAR AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param NCHAR) RETURN varchar(2000) CHARSET utf8
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',2000)));;
+LENGTH(f1(REPEAT('a',2000)))
+2000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" text CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param BINARY) RETURN BINARY AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param BINARY) RETURN varbinary(2000)
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',2000)));;
+LENGTH(f1(REPEAT('a',2000)))
+2000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" blob DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param VARCHAR) RETURN VARCHAR AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param VARCHAR) RETURN varchar(4000) CHARSET latin1
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',4000)));;
+LENGTH(f1(REPEAT('a',4000)))
+4000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" text DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param VARCHAR2) RETURN varchar(4000) CHARSET latin1
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',4000)));;
+LENGTH(f1(REPEAT('a',4000)))
+4000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" text DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param NVARCHAR) RETURN NVARCHAR AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param NVARCHAR) RETURN varchar(4000) CHARSET utf8
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',4000)));;
+LENGTH(f1(REPEAT('a',4000)))
+4000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" text CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param VARBINARY) RETURN VARBINARY AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param VARBINARY) RETURN varbinary(4000)
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',4000)));;
+LENGTH(f1(REPEAT('a',4000)))
+4000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" blob DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(param RAW) RETURN RAW AS BEGIN RETURN param; END;;
+SHOW CREATE FUNCTION f1;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param RAW) RETURN varbinary(4000)
+AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
+SELECT LENGTH(f1(REPEAT('a',4000)));;
+LENGTH(f1(REPEAT('a',4000)))
+4000
+CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" blob DEFAULT NULL
+)
+DROP TABLE t1;
+DROP FUNCTION f1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-row.result b/mysql-test/suite/compat/oracle/r/sp-row.result
new file mode 100644
index 00000000000..86b6b9a530b
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-row.result
@@ -0,0 +1,3072 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+#
+# ROW of ROWs is not supported yet
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a ROW(a INT));
+BEGIN
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT));
+BEGIN
+END' at line 3
+#
+# Returning the entire ROW parameter from a function
+#
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURN INT
+AS
+BEGIN
+RETURN a;
+END;
+$$
+SELECT f1(ROW(10,20));
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# ROW as an SP parameter
+#
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURN INT
+AS
+BEGIN
+RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT,b INT):=(11,21);
+BEGIN
+SELECT f1(a);
+END;
+$$
+SELECT f1(ROW(10,20));
+f1(ROW(10,20))
+20
+SELECT f1(10);
+ERROR 21000: Operand should contain 2 column(s)
+SELECT f1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1();
+f1(a)
+21
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+AS
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CALL p1(ROW(10,20));
+a.a a.b
+10 20
+CALL p1(10);
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# ROW as an SP OUT parameter
+#
+CREATE PROCEDURE p1(a OUT ROW(a INT,b INT))
+AS
+BEGIN
+a.a:=10;
+a.b:=20;
+END;
+$$
+CREATE PROCEDURE p2
+AS
+a ROW(a INT,b INT):=(11,21);
+BEGIN
+CALL p1(a);
+SELECT a.a,a.b;
+END;
+$$
+CALL p2();
+a.a a.b
+10 20
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+#
+# ROW as an SP return value is not supported yet
+#
+CREATE FUNCTION p1() RETURN ROW(a INT)
+AS
+BEGIN
+RETURN NULL;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT)
+AS
+BEGIN
+RETURN NULL;
+END' at line 1
+#
+# Diplicate row field
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT, a DOUBLE);
+BEGIN
+SELECT a.a;
+END;
+$$
+ERROR 42S21: Duplicate column name 'a'
+#
+# Bad scalar default value
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT, b DOUBLE):= 1;
+BEGIN
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Bad ROW default value with a wrong number of fields
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT, b DOUBLE):= ROW(1,2,3);
+BEGIN
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Scalar variable vs table alias cause no ambiguity
+#
+CREATE PROCEDURE p1()
+AS
+a INT;
+BEGIN
+-- a.x is a table column here (not a row variable field)
+SELECT a.x FROM a;
+SELECT a.x FROM t1 a;
+END;
+$$
+DROP PROCEDURE p1;
+#
+# Using the entire ROW variable in select list
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW variable in functions
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Comparing the entire ROW to a scalar value
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT a=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT 1=a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Passing the entire ROW to a stored function
+#
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT f1(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT f1(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+#
+# Assigning a scalar value to a ROW variable with 1 column
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT);
+BEGIN
+rec:=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a scalar value to a ROW variable with 2 columns
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec:=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a ROW value to a ROW variable with different number of columns
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec:=ROW(1,2,3);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Returning the entire ROW from a function is not supported yet
+# This syntax would be needed: SELECT f1().x FROM DUAL;
+#
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+rec ROW(a INT);
+BEGIN
+RETURN rec;
+END;
+$$
+SELECT f1(10);
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# Using the entire ROW in SELECT..CREATE
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW in LIMIT
+#
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= '10';
+SELECT * FROM t1 LIMIT rec;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# Setting ROW fields using a SET command
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+a INT;
+BEGIN
+SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c a
+10 20 test 5
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from a ROW value
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec:=ROW(1,2);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1();
+rec.a rec.b
+1 2
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from another ROW value
+#
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT,b INT);
+rec2 ROW(a INT,b INT);
+BEGIN
+rec1:=ROW(1,2);
+rec2:=rec1;
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+1 2
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to a ROW() function
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:= 1;
+rec.b:= 2;
+SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+SELECT rec=(NULL,0), rec=ROW(NULL,0);
+SELECT rec=(NULL,2), rec=ROW(NULL,2);
+SELECT rec<>(0,0), rec<>ROW(0,0);
+SELECT rec<>(1,2), rec<>ROW(1,2);
+SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+SELECT rec IN ((0,NULL),(1,2));
+SELECT rec NOT IN ((0,NULL),(1,1));
+SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+CALL p1();
+rec=(0,0) rec=ROW(0,0) (0,0)=rec ROW(0,0)=rec
+0 0 0 0
+rec=(1,2) rec=ROW(1,2) (1,2)=rec ROW(1,2)=rec
+1 1 1 1
+rec=(NULL,0) rec=ROW(NULL,0)
+0 0
+rec=(NULL,2) rec=ROW(NULL,2)
+NULL NULL
+rec<>(0,0) rec<>ROW(0,0)
+1 1
+rec<>(1,2) rec<>ROW(1,2)
+0 0
+rec<>(NULL,0) rec<>ROW(NULL,0)
+1 1
+rec<>(NULL,2) rec<>ROW(NULL,2)
+NULL NULL
+rec IN ((0,0)) rec IN (ROW(0,0))
+0 0
+rec IN ((1,2)) rec IN (ROW(1,2))
+1 1
+rec IN ((0,NULL),(1,2))
+1
+rec NOT IN ((0,NULL),(1,1))
+1
+rec NOT IN ((1,NULL),(1,1))
+NULL
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to another ROW variable
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec1,rec2,rec3 ROW(a INT,b INT);
+BEGIN
+rec1.a:= 1;
+rec1.b:= 2;
+rec2.a:= 11;
+rec2.b:= 12;
+rec3.a:= 11;
+rec3.b:= 12;
+SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+CALL p1();
+rec1=rec2 rec2=rec1 rec2=rec3 rec3=rec2
+0 0 1 1
+DROP PROCEDURE p1;
+#
+# Referencing a non-existing row variable
+#
+CREATE PROCEDURE p1()
+AS
+BEGIN
+SET a.b=1;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'a'
+CREATE PROCEDURE p1()
+AS
+BEGIN
+a.b:=1;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'a'
+#
+# Referencing a non-existing row field
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT,b INT);
+BEGIN
+SELECT a.c FROM t1;
+END;
+$$
+ERROR HY000: Row variable 'a' does not have a field 'c'
+#
+# ROW and scalar variables with the same name shadowing each other
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT);
+BEGIN
+a.a:=100;
+DECLARE
+a INT:= 200;
+BEGIN
+SELECT a;
+DECLARE
+a ROW(a INT);
+BEGIN
+a.a:=300;
+SELECT a.a;
+END;
+SELECT a;
+END;
+SELECT a.a;
+END;
+$$
+CALL p1();
+a
+200
+a.a
+300
+a
+200
+a.a
+100
+DROP PROCEDURE p1;
+#
+# ROW with good default values
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT,b INT):= (10,20);
+b ROW(a INT,b INT):= (11,21);
+c ROW(a INT,b INT):= a;
+BEGIN
+SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+CALL p1;
+a.a a.b b.a b.b c.a c.b
+10 20 11 21 10 20
+DROP PROCEDURE p1;
+#
+# ROW in WHERE clause
+#
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT,b INT):=ROW(10,20);
+BEGIN
+SELECT * FROM t1 WHERE rec=ROW(a,b);
+SELECT * FROM t1 WHERE ROW(a,b)=rec;
+SELECT * FROM t1 WHERE rec=ROW(10,20);
+SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+CALL p1();
+a b
+10 20
+a b
+10 20
+a b
+10 20
+a b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in WHERE clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= 10;
+SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in HAVING clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= 10;
+SELECT * FROM t1 HAVING a=rec.a;
+SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in LIMIT clause
+#
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 LIMIT t1.a;
+ERROR 42000: Undeclared variable: t1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= 10;
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+a
+10
+20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+rec ROW(a VARCHAR(10));
+BEGIN
+rec.a:= '10';
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# ROW fields in select list
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+t1 ROW(a INT);
+BEGIN
+t1.a:= 10;
+SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+CALL p1();
+t1.a comm
+10 This is the variable t1.a value, rather than the column t1.a
+10 This is the variable t1.a value, rather than the column t1.a
+t1.a a t1.a+t2.a
+10 10 20
+10 20 30
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as insert values
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT, b VARCHAR(10));
+BEGIN
+rec.a:= 10;
+rec.b:= 'test';
+INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 test
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as SP out parameters
+#
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+a:= 10;
+b:= 'test';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+rec ROW(a INT, b VARCHAR(10));
+BEGIN
+CALL p1(rec.a, rec.b);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as dynamic SQL out parameters
+#
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+a:= 20;
+b:= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+rec ROW(a INT, b VARCHAR(30));
+BEGIN
+EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+20 test-dynamic-sql
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as SELECT..INTO targets
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT, b VARCHAR(10));
+BEGIN
+SELECT 10,'test' INTO rec.a,rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+#
+# Implicit default NULL handling
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+BEGIN
+SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d rec.e rec.f
+NULL NULL NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# NULL handling
+#
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT, b VARCHAR(10)):=(NULL,NULL);
+rec2 ROW(a INT, b VARCHAR(10)):=rec1;
+BEGIN
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (10,20);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (NULL,20);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (10,NULL);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (NULL,NULL);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+CALL p1;
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+rec1.a rec1.b rec2.a rec2.b
+10 20 10 20
+rec1.a rec1.b rec2.a rec2.b
+NULL 20 NULL 20
+rec1.a rec1.b rec2.a rec2.b
+10 NULL 10 NULL
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# Testing multiple ROW variable declarations
+# This makes sure that fill_field_definitions() is called only once
+# per a ROW field, so create length is not converted to internal length
+# multiple times.
+#
+CREATE PROCEDURE p1
+AS
+rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+BEGIN
+CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "rec1.a" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec2.a" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec3.a" varchar(10) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# INT
+#
+CREATE PROCEDURE p1() AS var INT; rec ROW(var INT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(1); rec ROW(var INT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(2); rec ROW(var INT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(3); rec ROW(var INT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(4); rec ROW(var INT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(5); rec ROW(var INT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(6); rec ROW(var INT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(7); rec ROW(var INT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(8); rec ROW(var INT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(9); rec ROW(var INT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(10); rec ROW(var INT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(11); rec ROW(var INT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(11) DEFAULT NULL,
+ "rec.var" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(12); rec ROW(var INT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(12) DEFAULT NULL,
+ "rec.var" int(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(13); rec ROW(var INT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(13) DEFAULT NULL,
+ "rec.var" int(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(14); rec ROW(var INT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(14) DEFAULT NULL,
+ "rec.var" int(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(20); rec ROW(var INT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(20) DEFAULT NULL,
+ "rec.var" int(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(21); rec ROW(var INT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(21) DEFAULT NULL,
+ "rec.var" int(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TINYINT
+#
+CREATE PROCEDURE p1() AS var TINYINT; rec ROW(var TINYINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(4) DEFAULT NULL,
+ "rec.var" tinyint(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(1); rec ROW(var TINYINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(4) DEFAULT NULL,
+ "rec.var" tinyint(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(2); rec ROW(var TINYINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(4) DEFAULT NULL,
+ "rec.var" tinyint(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(3); rec ROW(var TINYINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(4) DEFAULT NULL,
+ "rec.var" tinyint(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(4); rec ROW(var TINYINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(4) DEFAULT NULL,
+ "rec.var" tinyint(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(5); rec ROW(var TINYINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(5) DEFAULT NULL,
+ "rec.var" tinyint(5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(6); rec ROW(var TINYINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(6) DEFAULT NULL,
+ "rec.var" tinyint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(7); rec ROW(var TINYINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(7) DEFAULT NULL,
+ "rec.var" tinyint(7) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(8); rec ROW(var TINYINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(8) DEFAULT NULL,
+ "rec.var" tinyint(8) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(9); rec ROW(var TINYINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(9) DEFAULT NULL,
+ "rec.var" tinyint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(10); rec ROW(var TINYINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(10) DEFAULT NULL,
+ "rec.var" tinyint(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(11); rec ROW(var TINYINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(11) DEFAULT NULL,
+ "rec.var" tinyint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(12); rec ROW(var TINYINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(12) DEFAULT NULL,
+ "rec.var" tinyint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(13); rec ROW(var TINYINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(13) DEFAULT NULL,
+ "rec.var" tinyint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(14); rec ROW(var TINYINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(14) DEFAULT NULL,
+ "rec.var" tinyint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(20); rec ROW(var TINYINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(20) DEFAULT NULL,
+ "rec.var" tinyint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(21); rec ROW(var TINYINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinyint(21) DEFAULT NULL,
+ "rec.var" tinyint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SMALLINT
+#
+CREATE PROCEDURE p1() AS var SMALLINT; rec ROW(var SMALLINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(1); rec ROW(var SMALLINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(2); rec ROW(var SMALLINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(3); rec ROW(var SMALLINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(4); rec ROW(var SMALLINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(5); rec ROW(var SMALLINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(6); rec ROW(var SMALLINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(6) DEFAULT NULL,
+ "rec.var" smallint(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(7); rec ROW(var SMALLINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(7) DEFAULT NULL,
+ "rec.var" smallint(7) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(8); rec ROW(var SMALLINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(8) DEFAULT NULL,
+ "rec.var" smallint(8) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(9); rec ROW(var SMALLINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(9) DEFAULT NULL,
+ "rec.var" smallint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(10); rec ROW(var SMALLINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(10) DEFAULT NULL,
+ "rec.var" smallint(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(11); rec ROW(var SMALLINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(11) DEFAULT NULL,
+ "rec.var" smallint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(12); rec ROW(var SMALLINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(12) DEFAULT NULL,
+ "rec.var" smallint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(13); rec ROW(var SMALLINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(13) DEFAULT NULL,
+ "rec.var" smallint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(14); rec ROW(var SMALLINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(14) DEFAULT NULL,
+ "rec.var" smallint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(20); rec ROW(var SMALLINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(20) DEFAULT NULL,
+ "rec.var" smallint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(21); rec ROW(var SMALLINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" smallint(21) DEFAULT NULL,
+ "rec.var" smallint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MEDIUMINT
+#
+CREATE PROCEDURE p1() AS var MEDIUMINT; rec ROW(var MEDIUMINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(1); rec ROW(var MEDIUMINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(2); rec ROW(var MEDIUMINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(3); rec ROW(var MEDIUMINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(4); rec ROW(var MEDIUMINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(5); rec ROW(var MEDIUMINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(6); rec ROW(var MEDIUMINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(7); rec ROW(var MEDIUMINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(8); rec ROW(var MEDIUMINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(9); rec ROW(var MEDIUMINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(9) DEFAULT NULL,
+ "rec.var" mediumint(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(10); rec ROW(var MEDIUMINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(10) DEFAULT NULL,
+ "rec.var" mediumint(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(11); rec ROW(var MEDIUMINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(11) DEFAULT NULL,
+ "rec.var" mediumint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(12); rec ROW(var MEDIUMINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(12) DEFAULT NULL,
+ "rec.var" mediumint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(13); rec ROW(var MEDIUMINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(13) DEFAULT NULL,
+ "rec.var" mediumint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(14); rec ROW(var MEDIUMINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(14) DEFAULT NULL,
+ "rec.var" mediumint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(20); rec ROW(var MEDIUMINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(20) DEFAULT NULL,
+ "rec.var" mediumint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(21); rec ROW(var MEDIUMINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumint(21) DEFAULT NULL,
+ "rec.var" mediumint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# BIGINT
+#
+CREATE PROCEDURE p1() AS var BIGINT; rec ROW(var BIGINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(1); rec ROW(var BIGINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(2); rec ROW(var BIGINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(3); rec ROW(var BIGINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(4); rec ROW(var BIGINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(5); rec ROW(var BIGINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(6); rec ROW(var BIGINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(7); rec ROW(var BIGINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(8); rec ROW(var BIGINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(9); rec ROW(var BIGINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(10); rec ROW(var BIGINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(11); rec ROW(var BIGINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(12); rec ROW(var BIGINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(13); rec ROW(var BIGINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(14); rec ROW(var BIGINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(20); rec ROW(var BIGINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(21); rec ROW(var BIGINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(21) DEFAULT NULL,
+ "rec.var" bigint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DOUBLE
+#
+CREATE PROCEDURE p1() AS var DOUBLE; rec ROW(var DOUBLE); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double DEFAULT NULL,
+ "rec.var" double DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,1); rec ROW(var DOUBLE(30,1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,1) DEFAULT NULL,
+ "rec.var" double(30,1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,2); rec ROW(var DOUBLE(30,2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,2) DEFAULT NULL,
+ "rec.var" double(30,2) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,3); rec ROW(var DOUBLE(30,3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,3) DEFAULT NULL,
+ "rec.var" double(30,3) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,4); rec ROW(var DOUBLE(30,4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,4) DEFAULT NULL,
+ "rec.var" double(30,4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,5); rec ROW(var DOUBLE(30,5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,5) DEFAULT NULL,
+ "rec.var" double(30,5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,6); rec ROW(var DOUBLE(30,6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,6) DEFAULT NULL,
+ "rec.var" double(30,6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,7); rec ROW(var DOUBLE(30,7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,7) DEFAULT NULL,
+ "rec.var" double(30,7) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,8); rec ROW(var DOUBLE(30,8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,8) DEFAULT NULL,
+ "rec.var" double(30,8) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,9); rec ROW(var DOUBLE(30,9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,9) DEFAULT NULL,
+ "rec.var" double(30,9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,10); rec ROW(var DOUBLE(30,10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,10) DEFAULT NULL,
+ "rec.var" double(30,10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,11); rec ROW(var DOUBLE(30,11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,11) DEFAULT NULL,
+ "rec.var" double(30,11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,12); rec ROW(var DOUBLE(30,12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,12) DEFAULT NULL,
+ "rec.var" double(30,12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,13); rec ROW(var DOUBLE(30,13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,13) DEFAULT NULL,
+ "rec.var" double(30,13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,14); rec ROW(var DOUBLE(30,14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,14) DEFAULT NULL,
+ "rec.var" double(30,14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,20); rec ROW(var DOUBLE(30,20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,20) DEFAULT NULL,
+ "rec.var" double(30,20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,21); rec ROW(var DOUBLE(30,21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,21) DEFAULT NULL,
+ "rec.var" double(30,21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# VARCHAR
+#
+CREATE PROCEDURE p1() AS var CHAR; rec ROW(var CHAR); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(1) DEFAULT NULL,
+ "rec.var" varchar(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BINARY; rec ROW(var BINARY); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varbinary(1) DEFAULT NULL,
+ "rec.var" varbinary(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var CHAR(1); rec ROW(var CHAR(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(1) DEFAULT NULL,
+ "rec.var" varchar(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var CHAR(10); rec ROW(var CHAR(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) DEFAULT NULL,
+ "rec.var" varchar(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var NCHAR(10); rec ROW(var NCHAR(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" varchar(10) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BINARY(10); rec ROW(var BINARY(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varbinary(10) DEFAULT NULL,
+ "rec.var" varbinary(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARBINARY(10); rec ROW(var VARBINARY(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varbinary(10) DEFAULT NULL,
+ "rec.var" varbinary(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARCHAR(10); rec ROW(var VARCHAR(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) DEFAULT NULL,
+ "rec.var" varchar(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARCHAR(10) CHARACTER SET utf8; rec ROW(var VARCHAR(10) CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" varchar(10) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin; rec ROW(var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
+ "rec.var" varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TIME
+#
+CREATE PROCEDURE p1() AS var TIME; rec ROW(var TIME); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time DEFAULT NULL,
+ "rec.var" time DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(1); rec ROW(var TIME(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(1) DEFAULT NULL,
+ "rec.var" time(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(2); rec ROW(var TIME(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(2) DEFAULT NULL,
+ "rec.var" time(2) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(3); rec ROW(var TIME(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(3) DEFAULT NULL,
+ "rec.var" time(3) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(4); rec ROW(var TIME(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(4) DEFAULT NULL,
+ "rec.var" time(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(5); rec ROW(var TIME(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(5) DEFAULT NULL,
+ "rec.var" time(5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(6); rec ROW(var TIME(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(6) DEFAULT NULL,
+ "rec.var" time(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DATETIME
+#
+CREATE PROCEDURE p1() AS var DATETIME; rec ROW(var DATETIME); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime DEFAULT NULL,
+ "rec.var" datetime DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(1); rec ROW(var DATETIME(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(1) DEFAULT NULL,
+ "rec.var" datetime(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(2); rec ROW(var DATETIME(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(2) DEFAULT NULL,
+ "rec.var" datetime(2) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(3); rec ROW(var DATETIME(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(3) DEFAULT NULL,
+ "rec.var" datetime(3) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(4); rec ROW(var DATETIME(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(4) DEFAULT NULL,
+ "rec.var" datetime(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(5); rec ROW(var DATETIME(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(5) DEFAULT NULL,
+ "rec.var" datetime(5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(6); rec ROW(var DATETIME(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(6) DEFAULT NULL,
+ "rec.var" datetime(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# LOB
+#
+CREATE PROCEDURE p1() AS var TEXT; rec ROW(var TEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" text DEFAULT NULL,
+ "rec.var" text DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYTEXT; rec ROW(var TINYTEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" tinytext DEFAULT NULL,
+ "rec.var" tinytext DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMTEXT; rec ROW(var MEDIUMTEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumtext DEFAULT NULL,
+ "rec.var" mediumtext DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var LONGTEXT; rec ROW(var LONGTEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" longtext DEFAULT NULL,
+ "rec.var" longtext DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TEXT CHARACTER SET utf8; rec ROW(var TEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumtext CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" mediumtext CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYTEXT CHARACTER SET utf8; rec ROW(var TINYTEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" text CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" text CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMTEXT CHARACTER SET utf8; rec ROW(var MEDIUMTEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" longtext CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" longtext CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var LONGTEXT CHARACTER SET utf8; rec ROW(var LONGTEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" longtext CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" longtext CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
+#
+# MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
+#
+#
+# Referring to a table in a non-existing database
+#
+CREATE PROCEDURE p1()
+AS
+rec test2.t1%ROWTYPE;
+BEGIN
+NULL;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test2.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+ERROR 42S02: Table 'test2.t1' doesn't exist
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a table in the current database
+#
+CREATE PROCEDURE p1()
+AS
+rec t1%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a table in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+AS
+rec test.t1%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a view in the current database
+#
+CREATE PROCEDURE p1()
+AS
+rec v1%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Referring to a view in an explicitly specified database
+#
+CREATE PROCEDURE p1()
+AS
+rec test.v1%ROWTYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.v1' doesn't exist
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "rec.a" int(11) DEFAULT NULL,
+ "rec.b" varchar(10) DEFAULT NULL,
+ "rec.c" double DEFAULT NULL,
+ "rec.d" decimal(10,0) DEFAULT NULL
+)
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Checking that all table%ROWTYPE fields are NULL by default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+END;
+$$
+CALL p1();
+rec1.a rec1.b rec1.c rec1.d
+NULL NULL NULL NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A table%ROWTYPE variable with a ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE DEFAULT ROW(10,'bbb');
+BEGIN
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A table%ROWTYPE variable with an incompatible ROW expression as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE DEFAULT ROW(10,'bbb','ccc');
+BEGIN
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A table%ROWTYPE variable with a ROW variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 ROW(a INT, b VARCHAR(10)):= ROW(10,'bbb');
+rec2 t1%ROWTYPE DEFAULT rec1;
+BEGIN
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# A ROW variable using a table%ROWTYPE variable as a default
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE := ROW(10,'bbb');
+rec2 ROW(a INT, b VARCHAR(10)):= rec1;
+BEGIN
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 bbb
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning table%ROWTYPE variables with a different column count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+rec2 t2%ROWTYPE;
+BEGIN
+rec2:=rec1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+rec2 t2%ROWTYPE;
+BEGIN
+rec1:=rec2;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 3 column(s)
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning compatible table%ROWTYPE variables (equal number of fields)
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+rec2 t2%ROWTYPE;
+BEGIN
+rec1.a:= 10;
+rec1.b:= 'bbb';
+rec2:=rec1;
+SELECT rec2.x, rec2.y;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between incompatible table%ROWTYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+rec2 ROW(x INT,y INT,z INT);
+BEGIN
+rec2.x:= 10;
+rec2.y:= 20;
+rec2.z:= 30;
+rec1:= rec2;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning between compatible table%ROWTYPE and explicit ROW variables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+rec2 ROW(x INT,y INT);
+BEGIN
+rec2.x:= 10;
+rec2.y:= 20;
+rec1:= rec2;
+SELECT rec1.a, rec1.b;
+rec1.a:= 11;
+rec1.b:= 21;
+rec2:= rec1;
+SELECT rec2.x, rec2.y;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+rec2.x rec2.y
+11 21
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Assigning table%ROWTYPE from a ROW expression
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+rec1:= ROW(10,20);
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table%ROWTYPE variable with a wrong field count
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+CREATE PROCEDURE p1()
+AS
+rec2 t2%ROWTYPE;
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec2;
+CLOSE cur1;
+END;
+$$
+CALL p1();
+ERROR HY000: Incorrect number of FETCH variables
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table%ROWTYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+CREATE PROCEDURE p1()
+AS
+rec t1%ROWTYPE;
+CURSOR cur IS SELECT * FROM t1;
+BEGIN
+OPEN cur;
+LOOP
+FETCH cur INTO rec;
+EXIT WHEN cur%NOTFOUND;
+SELECT rec.a, rec.b, rec.c, rec.d;
+INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+END LOOP;
+CLOSE cur;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d
+10 bb1 11111.1 12.31
+rec.a rec.b rec.c rec.d
+20 bb2 22222.2 12.32
+rec.a rec.b rec.c rec.d
+30 bb3 33333.3 12.33
+SELECT * FROM t2;
+a b c d
+10 bb1 11111.1 12.31
+20 bb2 22222.2 12.32
+30 bb3 33333.3 12.33
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table%ROWTYPE variable with different column names
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+CREATE PROCEDURE p1()
+AS
+rec2 t2%ROWTYPE;
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.x, rec2.y;
+CLOSE cur1;
+END;
+$$
+CALL p1();
+rec2.x rec2.y
+10 bbb
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# Fetching a cursor into a table%ROWTYPE variable, with truncation
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+CREATE PROCEDURE p1()
+AS
+rec2 t2%ROWTYPE;
+CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+OPEN cur1;
+FETCH cur1 INTO rec2;
+SELECT rec2.a, rec2.b;
+CLOSE cur1;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+10 11
+Warnings:
+Warning 1265 Data truncated for column 'b' at row 1
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# table%ROWTYPE variables are not allowed in LIMIT
+#
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+CREATE PROCEDURE p1()
+AS
+rec1 t1%ROWTYPE:=(1,2);
+BEGIN
+SELECT * FROM t1 LIMIT rec1.a;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+DROP TABLE t1;
+#
+# table%ROWTYPE variable fields as OUT parameters
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a OUT INT,b OUT VARCHAR(10))
+AS
+BEGIN
+a:=10;
+b:='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+CALL p1(rec1.a, rec1.b);
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire table%ROWTYPE variable
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+rec1 t1%ROWTYPE:= ROW(10,'bb');
+BEGIN
+CALL p1(rec1);
+END;
+$$
+CALL p2();
+a.a a.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Passing the entire table%ROWTYPE variable as an OUT parameter
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1(a OUT ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+a:= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+rec1 t1%ROWTYPE;
+BEGIN
+CALL p1(rec1);
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p2();
+rec1.a rec1.b
+10 bb
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Assigning a table%ROWTYPE field to an OUT parameter
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1 (res IN OUT INTEGER)
+AS
+rec1 t1%ROWTYPE:=ROW(10,'b0');
+BEGIN
+res:=rec1.a;
+END;
+$$
+CALL p1(@res);
+SELECT @res;
+@res
+10
+SET @res=NULL;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing Item_splocal_row_field_by_name::print
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+rec t1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+EXPLAIN EXTENDED SELECT rec.a, rec.b;
+END;
+$$
+CALL p1();
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select rec.a@0["a"] AS "rec.a",rec.b@0["b"] AS "rec.b"
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Non-existing field
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+rec t1%ROWTYPE;
+BEGIN
+SELECT rec.c;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+ALTER TABLE t1 ADD c INT;
+CALL p1();
+rec.c
+NULL
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that field names are case insensitive
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+rec t1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+SELECT rec.A, rec.B;
+END;
+$$
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that table%ROWTYPE uses temporary tables vs shadowed real tables
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+rec t1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+SELECT rec.A, rec.B;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'A'
+DROP TEMPORARY TABLE t1;
+CALL p1();
+rec.A rec.B
+10 bb
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Testing that the structure of table%ROWTYPE variables is determined at the very beginning and is not changed after ALTER
+#
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+BEGIN
+ALTER TABLE t1 ADD c INT;
+DECLARE
+rec t1%ROWTYPE; -- this will not have column "c"
+ BEGIN
+rec.c:=10;
+END;
+END;
+$$
+CALL p1();
+ERROR HY000: Row variable 'rec' does not have a field 'c'
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MDEV-12291 Allow ROW variables as SELECT INTO targets
+#
+# ROW variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+rec1 ROW(a INT, b VARCHAR(32), c DOUBLE);
+BEGIN
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: The used SELECT statements have a different number of columns
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# Multiple ROW variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+SELECT * FROM t1 INTO rec1, rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# ROW variables working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# table%ROWTYPE variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+rec1 t1%ROWTYPE;
+BEGIN
+SELECT 10,'a','b' FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: The used SELECT statements have a different number of columns
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# Multiple table%ROWTYPE variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+rec1 t1%ROWTYPE;
+BEGIN
+SELECT 10,'a' FROM t1 INTO rec1, rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# table%ROWTYPE working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+rec1 t1%ROWTYPE;
+BEGIN
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# cursor%ROWTYPE variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+CURSOR cur1 IS SELECT 10, 'b0', 'c0';
+rec1 cur1%ROWTYPE;
+BEGIN
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: The used SELECT statements have a different number of columns
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# Multiple cursor%ROWTYPE variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+CURSOR cur1 IS SELECT * FROM t1;
+rec1 cur1%ROWTYPE;
+BEGIN
+SELECT * FROM t1 INTO rec1, rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+# cursor%ROWTYPE working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+CREATE PROCEDURE p1 AS
+CURSOR cur1 IS SELECT * FROM t1;
+rec1 cur1%ROWTYPE;
+BEGIN
+SELECT * FROM t1 INTO rec1;
+SELECT rec1.a, rec1.b;
+END;
+$$
+CALL p1();
+rec1.a rec1.b
+10 b10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MDEV-12347 Valgrind reports invalid read errors in Item_field_row::element_index_by_name
+#
+CREATE TABLE t1 (a INT, b ENUM('b0','b1','b12','b3'));
+CREATE PROCEDURE p1 AS
+BEGIN
+DECLARE
+rec t1%ROWTYPE;
+BEGIN
+rec.b:='b0';
+SELECT rec.b;
+END;
+END;
+$$
+CALL p1();
+rec.b
+b0
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE TABLE t1 (a INT, b SET('b0','b1','b12','b3'));
+CREATE PROCEDURE p1 AS
+BEGIN
+DECLARE
+rec t1%ROWTYPE;
+BEGIN
+rec.b:='b0';
+SELECT rec.b;
+END;
+END;
+$$
+CALL p1();
+rec.b
+b0
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MDEV-13273 Confusion between table alias and ROW type variable
+#
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1
+AS
+a INT;
+b INT;
+BEGIN
+-- a.c1 is a table column
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 0;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1
+AS
+a ROW (c1 INT, c2 INT) := ROW(101,102);
+b INT;
+BEGIN
+-- a.c1 is a ROW variable field
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 102;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+101
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1
+AS
+a t1%ROWTYPE := ROW (10,20);
+b INT;
+BEGIN
+-- a.c1 is a ROW variable field
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 20;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+10
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+CREATE PROCEDURE p1
+AS
+CURSOR cur1 IS SELECT * FROM t1;
+a cur1%ROWTYPE := ROW (10,20);
+b INT;
+BEGIN
+-- a.c1 is a ROW variable field
+SELECT a.c1 INTO b
+FROM t1 a
+WHERE a.c2 = 20;
+SELECT b;
+END;
+$$
+CALL p1;
+b
+10
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/sp-security.result b/mysql-test/suite/compat/oracle/r/sp-security.result
new file mode 100644
index 00000000000..b98ecaca972
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-security.result
@@ -0,0 +1,288 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+#
+#
+# Initiation:
+# - creating database db1
+# - creating user user1 with access rights to db1
+#
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (a INT, b VARCHAR(10));
+CREATE USER user1;
+GRANT ALL PRIVILEGES ON test.* TO user1;
+connect conn1,localhost,user1,,test;
+SET sql_mode=ORACLE;
+SELECT database();
+database()
+test
+SELECT user();
+user()
+user1@localhost
+#
+# Making sure that user1 does not have privileges to db1.t1
+#
+SHOW CREATE TABLE db1.t1;
+ERROR 42000: SHOW command denied to user 'user1'@'localhost' for table 't1'
+SHOW FIELDS IN db1.t1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+#
+# Trigger: using %TYPE with a table we don't have access to
+#
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+a b
+10 20
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+DECLARE b db1.t1.b%TYPE := 20;
+BEGIN
+:NEW.b := 10;
+END;
+END
+$$
+INSERT INTO t1 (a) VALUES (10);
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+SELECT * FROM t1;
+a b
+10 20
+DROP TRIGGER tr1;
+DROP TABLE t1;
+#
+# Stored procedure: Using %TYPE for with a table that we don't have access to
+# DEFINER user1, SQL SECURITY DEFAULT
+#
+CREATE PROCEDURE p1()
+AS
+a db1.t1.a%TYPE := 10;
+BEGIN
+SELECT a;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a db1.t1%ROWTYPE;
+BEGIN
+SELECT a.a;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+#
+# Stored procedure: Using %TYPE for with a table that we don't have access to
+# DEFINER root, SQL SECURITY INVOKER
+#
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+AS
+a db1.t1.a%TYPE := 10;
+BEGIN
+SELECT a;
+END;
+$$
+connection conn1;
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+AS
+a db1.t1%ROWTYPE;
+BEGIN
+SELECT a.a;
+END;
+$$
+connection conn1;
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP PROCEDURE p1;
+#
+# Stored procedure: Using %TYPE for with a table that we don't have access to
+# DEFINER root, SQL SECURITY DEFINER
+#
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+AS
+a db1.t1.a%TYPE := 10;
+BEGIN
+SELECT a;
+END;
+$$
+connection conn1;
+CALL p1;
+a
+10
+DROP PROCEDURE p1;
+connection default;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+AS
+a db1.t1%ROWTYPE;
+BEGIN
+a.a:= 10;
+SELECT a.a;
+END;
+$$
+connection conn1;
+CALL p1;
+a.a
+10
+DROP PROCEDURE p1;
+#
+# Stored function: Using %TYPE for with a table that we don't have access to
+# DEFINER user1, SQL SECURITY DEFAULT
+#
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1() RETURN INT
+AS
+a db1.t1.a%TYPE:=0;
+BEGIN
+RETURN OCTET_LENGTH(a);
+END;
+$$
+SELECT f1();
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Stored function: Using %TYPE for with a table that we don't have access to
+# DEFINER root, SQL SECURITY INVOKER
+#
+connection default;
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1() RETURN INT
+SQL SECURITY INVOKER
+AS
+a db1.t1.a%TYPE:=0;
+BEGIN
+RETURN OCTET_LENGTH(a);
+END;
+$$
+connection conn1;
+SELECT f1();
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Stored function: Using %TYPE for with a table that we don't have access to
+# DEFINER root, SQL SECURITY DEFINER
+#
+connection default;
+CREATE TABLE t1 (a INT);
+CREATE FUNCTION f1() RETURN INT
+SQL SECURITY DEFINER
+AS
+a db1.t1.a%TYPE:=0;
+BEGIN
+RETURN OCTET_LENGTH(a);
+END;
+$$
+connection conn1;
+SELECT f1();
+f1()
+1
+DROP FUNCTION f1;
+DROP TABLE t1;
+connection default;
+GRANT SELECT (a) ON db1.t1 TO user1;
+connection conn1;
+#
+# Making sure that user1 has access to db1.t1.a, but not to db1.t1.b
+#
+SHOW CREATE TABLE db1.t1;
+ERROR 42000: SHOW command denied to user 'user1'@'localhost' for table 't1'
+SHOW FIELDS IN db1.t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+#
+# Trigger: Per-column privileges
+#
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+a b
+10 20
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+DECLARE a db1.t1.a%TYPE := 20;
+BEGIN
+:NEW.b := 10;
+END;
+END
+$$
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+a b
+10 20
+10 10
+DROP TRIGGER tr1;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+DECLARE b db1.t1.b%TYPE := 20;
+BEGIN
+:NEW.b := 10;
+END;
+END
+$$
+INSERT INTO t1 (a) VALUES (10);
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
+SELECT * FROM t1;
+a b
+10 20
+10 10
+DROP TRIGGER tr1;
+DROP TABLE t1;
+#
+# Stored procedure: Per-column privileges
+# DEFINER user1, SQL SECURITY DEFAULT
+#
+CREATE PROCEDURE p1()
+AS
+a db1.t1.a%TYPE := 10;
+BEGIN
+SELECT a;
+END;
+$$
+CALL p1;
+a
+10
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+b db1.t1.b%TYPE := 10;
+BEGIN
+SELECT b;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+b db1.t1%ROWTYPE;
+BEGIN
+b.b:=10;
+SELECT b.b;
+END;
+$$
+CALL p1;
+ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
+DROP PROCEDURE p1;
+#
+# Clean up
+#
+disconnect conn1;
+connection default;
+DROP USER user1;
+DROP DATABASE db1;
+#
+# End of MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+#
diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result
new file mode 100644
index 00000000000..a9158259f4a
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp.result
@@ -0,0 +1,2284 @@
+SET sql_mode=ORACLE;
+# Testing routines with no parameters
+CREATE FUNCTION f1 RETURN INT
+AS
+BEGIN
+RETURN 10;
+END;
+/
+SHOW CREATE FUNCTION f1;
+Function f1
+sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER
+Create Function CREATE DEFINER="root"@"localhost" FUNCTION "f1"() RETURN int(11)
+AS
+BEGIN
+RETURN 10;
+END
+character_set_client latin1
+collation_connection latin1_swedish_ci
+Database Collation latin1_swedish_ci
+SELECT f1();
+f1()
+10
+DROP FUNCTION f1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+SET @a=10;
+END;
+/
+SHOW CREATE PROCEDURE p1;
+Procedure p1
+sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER
+Create Procedure CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+BEGIN
+SET @a=10;
+END
+character_set_client latin1
+collation_connection latin1_swedish_ci
+Database Collation latin1_swedish_ci
+SET @a=0;
+CALL p1();
+SELECT @a;
+@a
+10
+DROP PROCEDURE p1;
+# Testing ":=" to set the default value of a variable
+CREATE FUNCTION f1 () RETURN NUMBER(10) AS
+a NUMBER(10) := 10;
+BEGIN
+DECLARE
+b NUMBER(10) DEFAULT 3;
+BEGIN
+RETURN a+b;
+END;
+END;
+/
+SELECT f1();
+f1()
+13
+DROP FUNCTION f1;
+# Testing labels
+CREATE FUNCTION f1 (a INT) RETURN CLOB AS
+BEGIN
+<<label1>>
+BEGIN
+IF a = 1 THEN
+LEAVE label1;
+END IF;
+RETURN 'IS NOT 1';
+END label1;
+RETURN 'IS 1';
+END;
+/
+SELECT f1(1);
+f1(1)
+IS 1
+SELECT f1(2);
+f1(2)
+IS NOT 1
+DROP FUNCTION f1;
+CREATE FUNCTION f1 (a INT) RETURN INT IS
+BEGIN
+<<label1>>
+LOOP
+IF a = 2 THEN
+LEAVE label1;
+END IF;
+SET a= a-1;
+END LOOP;
+RETURN a;
+END;
+/
+SELECT f1(4);
+f1(4)
+2
+DROP FUNCTION f1;
+CREATE FUNCTION f1 (a INT) RETURN INT AS
+BEGIN
+<<label1>>
+WHILE a>0 LOOP
+IF a = 2 THEN
+LEAVE label1;
+END IF;
+SET a= a-1;
+END LOOP label1;
+RETURN a;
+END;
+/
+SELECT f1(4);
+f1(4)
+2
+DROP FUNCTION f1;
+CREATE FUNCTION f1 (a INT) RETURN INT AS
+BEGIN
+<<label1>>
+REPEAT
+IF a = 2 THEN
+LEAVE label1;
+END IF;
+SET a= a-1;
+UNTIL a=0 END REPEAT;
+RETURN a;
+END;
+/
+SELECT f1(4);
+f1(4)
+2
+DROP FUNCTION f1;
+# Testing IN/OUT/INOUT
+CREATE PROCEDURE p1 (p1 IN VARCHAR2(10), p2 OUT VARCHAR2(10)) AS
+BEGIN
+SET p1='p1new';
+SET p2='p2new';
+END;
+/
+SET @p1='p1', @p2='p2';
+CALL p1(@p1, @p2);
+SELECT @p1, @p2;
+@p1 @p2
+p1 p2new
+DROP PROCEDURE p1;
+# Testing Oracle-style assigment
+CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10)) AS
+BEGIN
+p1:= 'p1new';
+END;
+/
+SET @p1='p1';
+CALL p1(@p1);
+SELECT @p1;
+@p1
+p1new
+DROP PROCEDURE p1;
+# Testing that NULL is a valid statement
+CREATE PROCEDURE p1(a INT) AS
+BEGIN
+NULL;
+END;
+/
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(a INT) AS
+a INT:=10;
+BEGIN
+IF a=10 THEN NULL; ELSE NULL; END IF;
+END;
+/
+DROP PROCEDURE p1;
+# Testing that (some) keyword_sp are allowed in Oracle-style assignments
+CREATE PROCEDURE p1 (action OUT INT) AS BEGIN action:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (clob OUT INT) AS BEGIN clob:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (enum OUT INT) AS BEGIN enum:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (via OUT INT) AS BEGIN via:=10; END;/
+DROP PROCEDURE p1/
+# Testing keyword_directly_assignable
+CREATE PROCEDURE p1 (ascii OUT INT) AS BEGIN ascii:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (backup OUT INT) AS BEGIN backup:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (binlog OUT INT) AS BEGIN binlog:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (byte OUT INT) AS BEGIN byte:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (cache OUT INT) AS BEGIN cache:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (checksum OUT INT) AS BEGIN checksum:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (checkpoint OUT INT) AS BEGIN checkpoint:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_add OUT INT) AS BEGIN column_add:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_check OUT INT) AS BEGIN column_check:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_create OUT INT) AS BEGIN column_create:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_delete OUT INT) AS BEGIN column_delete:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_get OUT INT) AS BEGIN column_get:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (deallocate OUT INT) AS BEGIN deallocate:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (examined OUT INT) AS BEGIN examined:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (execute OUT INT) AS BEGIN execute:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (flush OUT INT) AS BEGIN flush:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (format OUT INT) AS BEGIN format:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (get OUT INT) AS BEGIN get:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (help OUT INT) AS BEGIN help:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (host OUT INT) AS BEGIN host:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (install OUT INT) AS BEGIN install:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (option OUT INT) AS BEGIN option:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (options OUT INT) AS BEGIN options:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (owner OUT INT) AS BEGIN owner:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (parser OUT INT) AS BEGIN parser:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (port OUT INT) AS BEGIN port:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (prepare OUT INT) AS BEGIN prepare:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (remove OUT INT) AS BEGIN remove:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (reset OUT INT) AS BEGIN reset:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (restore OUT INT) AS BEGIN restore:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (security OUT INT) AS BEGIN security:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (server OUT INT) AS BEGIN server:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (signed OUT INT) AS BEGIN signed:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (socket OUT INT) AS BEGIN socket:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (slave OUT INT) AS BEGIN slave:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (slaves OUT INT) AS BEGIN slaves:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (soname OUT INT) AS BEGIN soname:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (start OUT INT) AS BEGIN start:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (stop OUT INT) AS BEGIN stop:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (stored OUT INT) AS BEGIN stored:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (unicode OUT INT) AS BEGIN unicode:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (uninstall OUT INT) AS BEGIN uninstall:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (upgrade OUT INT) AS BEGIN upgrade:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (wrapper OUT INT) AS BEGIN wrapper:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (xa OUT INT) AS BEGIN xa:=10; END;/
+DROP PROCEDURE p1/
+# Testing that keyword_directly_not_assignable does not work in :=
+CREATE PROCEDURE p1 (commit OUT INT) AS BEGIN commit:=10; END;/
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1
+CREATE PROCEDURE p1 (rollback OUT INT) AS BEGIN rollback:=10; END;/
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1
+CREATE PROCEDURE p1 (shutdown OUT INT) AS BEGIN shutdown:=10; END;/
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1
+# Testing that keyword_directly_not_assignable works in SET statements.
+CREATE PROCEDURE p1 (contains OUT INT) AS BEGIN SET contains=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (language OUT INT) AS BEGIN SET language=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (no OUT INT) AS BEGIN SET no=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (charset OUT INT) AS BEGIN SET charset=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (do OUT INT) AS BEGIN SET do=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (repair OUT INT) AS BEGIN SET repair=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (handler OUT INT) AS BEGIN SET handler=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (open OUT INT) AS BEGIN SET open=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (close OUT INT) AS BEGIN SET close=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (savepoint OUT INT) AS BEGIN SET savepoint=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (truncate OUT INT) AS BEGIN SET truncate=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (begin OUT INT) AS BEGIN SET begin=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (end OUT INT) AS BEGIN SET end=10; END;/
+DROP PROCEDURE p1/
+# Testing that keyword_directly_not_assignable works in table/column names
+CREATE TABLE contains (contains INT);
+DROP TABLE contains;
+CREATE TABLE language (language INT);
+DROP TABLE language;
+CREATE TABLE no (no INT);
+DROP TABLE no;
+CREATE TABLE charset (charset INT);
+DROP TABLE charset;
+CREATE TABLE do (do INT);
+DROP TABLE do;
+CREATE TABLE repair (repair INT);
+DROP TABLE repair;
+CREATE TABLE handler (handler INT);
+DROP TABLE handler;
+CREATE TABLE open (open INT);
+DROP TABLE open;
+CREATE TABLE close (close INT);
+DROP TABLE close;
+CREATE TABLE savepoint (savepoint INT);
+DROP TABLE savepoint;
+CREATE TABLE truncate (truncate INT);
+DROP TABLE truncate;
+CREATE TABLE begin (begin INT);
+DROP TABLE begin;
+CREATE TABLE end (end INT);
+DROP TABLE end;
+# Testing ELSIF
+CREATE FUNCTION f1(a INT) RETURN CLOB
+AS
+BEGIN
+IF a=1 THEN RETURN 'a is 1';
+ELSIF a=2 THEN RETURN 'a is 2';
+ELSE RETURN 'a is unknown';
+END IF;
+END;
+/
+SELECT f1(2) FROM DUAL;
+f1(2)
+a is 2
+DROP FUNCTION f1;
+# Testing top-level declarations
+CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
+AS
+p2 VARCHAR(10);
+BEGIN
+p2:='p1new';
+p1:=p2;
+END;
+/
+SET @p1='p1';
+CALL p1(@p1);
+SELECT @p1;
+@p1
+p1new
+DROP PROCEDURE p1;
+CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURN VARCHAR(20)
+AS
+p2 VARCHAR(10);
+BEGIN
+p2:='new';
+RETURN CONCAT(p1, p2);
+END;
+/
+SET @p1='p1';
+SELECT f1(@p1);
+f1(@p1)
+p1new
+DROP FUNCTION f1;
+# Testing non-top declarations
+CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
+AS
+BEGIN
+DECLARE
+p2 VARCHAR(10);
+BEGIN
+p2:='p1new';
+p1:=p2;
+END;
+DECLARE
+t1 VARCHAR(10);
+t2 VARCHAR(10);
+BEGIN
+END;
+END;
+/
+SET @p1='p1';
+CALL p1(@p1);
+SELECT @p1;
+@p1
+p1new
+DROP PROCEDURE p1;
+CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURN VARCHAR(20)
+AS
+BEGIN
+DECLARE
+p2 VARCHAR(10);
+BEGIN
+p2:='new';
+RETURN CONCAT(p1, p2);
+END;
+DECLARE
+t1 VARCHAR(10);
+t2 VARCHAR(10);
+BEGIN
+END;
+END;
+/
+SET @p1='p1';
+SELECT f1(@p1);
+f1(@p1)
+p1new
+DROP FUNCTION f1;
+# Testing exceptions
+CREATE TABLE t1 (c1 INT);
+CREATE PROCEDURE sp1 (p1 IN VARCHAR2(20), p2 OUT VARCHAR2(30))
+IS
+v1 INT;
+BEGIN
+SELECT c1 INTO v1 FROM t1;
+p2 := p1;
+EXCEPTION
+WHEN NOT FOUND THEN
+BEGIN
+p2 := 'def';
+END;
+END;
+/
+CALL sp1('abc', @a);
+SELECT @a;
+@a
+def
+DROP PROCEDURE sp1;
+DROP TABLE t1;
+CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT)
+IS
+BEGIN
+SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!';
+v:= 223;
+EXCEPTION
+WHEN 30001 THEN
+BEGIN
+v:= 113;
+END;
+END;
+/
+SET @v=10;
+CALL sp1(@v, 30001);
+CALL sp1(@v, 30002);
+ERROR 45000: User defined error!
+SELECT @v;
+@v
+113
+DROP PROCEDURE sp1;
+CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT)
+IS
+BEGIN
+BEGIN
+BEGIN
+SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!';
+v:= 223;
+EXCEPTION
+WHEN 30001 THEN
+BEGIN
+v:= 113;
+END;
+END;
+END;
+END;
+/
+SET @v=10;
+CALL sp1(@v, 30001);
+SELECT @v;
+@v
+113
+SET @v=10;
+CALL sp1(@v, 30002);
+ERROR 45000: User defined error!
+SELECT @v;
+@v
+10
+DROP PROCEDURE sp1;
+#
+# Testing EXIT statement
+#
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+EXIT;
+END;
+/
+ERROR 42000: EXIT with no matching label:
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+<<lable1>>
+BEGIN
+<<label2>>
+LOOP
+EXIT label1;
+END LOOP;
+END;
+END;
+/
+ERROR 42000: EXIT with no matching label: label1
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+LOOP
+LOOP
+i:= i + 1;
+IF i >= 5 THEN
+EXIT;
+END IF;
+END LOOP;
+i:= i + 100;
+EXIT;
+END LOOP;
+RETURN i;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+105
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+<<label1>>
+LOOP
+<<label2>>
+LOOP
+i:= i + 1;
+IF i >= 5 THEN
+EXIT label2;
+END IF;
+END LOOP;
+i:= i + 100;
+EXIT;
+END LOOP;
+RETURN i;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+105
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+<<label1>>
+LOOP
+<<label2>>
+LOOP
+i:= i + 1;
+IF i >= 5 THEN
+EXIT label1;
+END IF;
+END LOOP;
+i:= i + 100;
+EXIT;
+END LOOP;
+RETURN i;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+5
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+LOOP
+i:= i + 1;
+EXIT WHEN i >=5;
+END LOOP;
+RETURN i;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+5
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+<<label1>>
+LOOP
+<<label2>>
+LOOP
+i:= i + 1;
+EXIT label2 WHEN i >= 5;
+END LOOP;
+i:= i + 100;
+EXIT;
+END LOOP;
+RETURN i;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+105
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+IS
+i INT := 0;
+BEGIN
+<<label1>>
+LOOP
+<<label2>>
+LOOP
+i:= i + 1;
+EXIT label1 WHEN i >= 5;
+END LOOP;
+i:= i + 100;
+EXIT;
+END LOOP;
+RETURN i;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+5
+DROP FUNCTION f1;
+# Testing CURSOR declaration
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE FUNCTION f1 RETURN INT
+AS
+v_a INT:=10;
+CURSOR c IS SELECT a FROM t1;
+BEGIN
+OPEN c;
+FETCH c INTO v_a;
+CLOSE c;
+RETURN v_a;
+EXCEPTION
+WHEN OTHERS THEN RETURN -1;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+1
+DROP FUNCTION f1;
+DROP TABLE t1;
+# Testing RETURN in procedures
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+RETURN 10;
+END;
+/
+ERROR 42000: RETURN is only allowed in a FUNCTION
+CREATE FUNCTION f1 (a INT) RETURN INT
+AS
+BEGIN
+RETURN;
+END;
+/
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ';
+END' at line 4
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+IF a < 10 THEN
+BEGIN
+a:= a - 1;
+RETURN;
+END;
+END IF;
+a:= a + 1;
+EXCEPTION
+WHEN OTHERS THEN RETURN;
+END;
+/
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+11
+SET @v=9;
+CALL p1(@v);
+SELECT @v;
+@v
+8
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+DROP TABLE t1_non_existent;
+EXCEPTION
+WHEN OTHERS THEN
+BEGIN
+a:= 100;
+RETURN;
+END;
+END;
+/
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+@v
+100
+DROP PROCEDURE p1;
+# Testing WHILE loop
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+i INT:= 1;
+j INT:= 3;
+BEGIN
+WHILE i<=j
+LOOP
+a:= a + i;
+i:= i + 1;
+END LOOP;
+END;
+/
+SET @v=0;
+CALL p1(@v);
+SELECT @v;
+@v
+6
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+i INT:= 1;
+j INT:= 3;
+BEGIN
+<<label>>
+WHILE i<=j
+LOOP
+a:= a + i;
+i:= i + 1;
+END LOOP label;
+END;
+/
+SET @v=0;
+CALL p1(@v);
+SELECT @v;
+@v
+6
+DROP PROCEDURE p1;
+# Testing the FOR loop statement
+CREATE TABLE t1 (a INT);
+FOR i IN 1..3
+LOOP
+INSERT INTO t1 VALUES (i);
+END LOOP;
+/
+SELECT * FROM t1;
+a
+1
+2
+3
+DROP TABLE t1;
+CREATE FUNCTION f1 (lower_bound INT, upper_bound INT, lim INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+FOR i IN lower_bound . . upper_bound
+LOOP
+NULL
+END LOOP;
+RETURN total;
+END;
+/
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '. upper_bound
+LOOP
+NULL
+END LOOP;
+RETURN total;
+END' at line 5
+CREATE FUNCTION f1 (lower_bound INT, upper_bound INT, lim INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+FOR i IN lower_bound .. upper_bound
+LOOP
+total:= total + i;
+IF i = lim THEN
+EXIT;
+END IF;
+-- Bounds are calculated only once.
+-- The below assignments have no effect on the loop condition
+lower_bound:= 900;
+upper_bound:= 1000;
+END LOOP;
+RETURN total;
+END;
+/
+SELECT f1(1, 3, 100) FROM DUAL;
+f1(1, 3, 100)
+6
+SELECT f1(1, 3, 2) FROM DUAL;
+f1(1, 3, 2)
+3
+DROP FUNCTION f1;
+CREATE FUNCTION f1 RETURN INT
+AS
+total INT := 0;
+BEGIN
+FOR i IN 1 .. 5
+LOOP
+total:= total + 1000;
+FOR j IN 1 .. 5
+LOOP
+total:= total + 1;
+IF j = 3 THEN
+EXIT; -- End the internal loop
+END IF;
+END LOOP;
+END LOOP;
+RETURN total;
+END;
+/
+SELECT f1() FROM DUAL;
+f1()
+5015
+DROP FUNCTION f1;
+CREATE FUNCTION f1 (a INT, b INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+FOR i IN REVERSE a..1
+LOOP
+total:= total + i;
+IF i = b THEN
+EXIT;
+END IF;
+END LOOP;
+RETURN total;
+END
+/
+SELECT f1(3, 100) FROM DUAL;
+f1(3, 100)
+6
+SELECT f1(3, 2) FROM DUAL;
+f1(3, 2)
+5
+DROP FUNCTION f1;
+# Testing labeled FOR LOOP statement
+CREATE FUNCTION f1 (a INT, limita INT, b INT, limitb INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+<<la>>
+FOR ia IN 1 .. a
+LOOP
+total:= total + 1000;
+<<lb>>
+FOR ib IN 1 .. b
+LOOP
+total:= total + 1;
+EXIT lb WHEN ib = limitb;
+EXIT la WHEN ia = limita;
+END LOOP lb;
+END LOOP la;
+RETURN total;
+END;
+/
+SELECT f1(1, 1, 1, 1) FROM DUAL;
+f1(1, 1, 1, 1)
+1001
+SELECT f1(1, 2, 1, 2) FROM DUAL;
+f1(1, 2, 1, 2)
+1001
+SELECT f1(2, 1, 2, 1) FROM DUAL;
+f1(2, 1, 2, 1)
+2002
+SELECT f1(2, 1, 2, 2) FROM DUAL;
+f1(2, 1, 2, 2)
+1001
+SELECT f1(2, 2, 2, 2) FROM DUAL;
+f1(2, 2, 2, 2)
+2003
+SELECT f1(2, 3, 2, 3) FROM DUAL;
+f1(2, 3, 2, 3)
+2004
+DROP FUNCTION f1;
+# Testing labeled ITERATE in a labeled FOR LOOP statement
+CREATE FUNCTION f1 (a INT, b INT, blim INT) RETURN INT
+AS
+total INT := 0;
+BEGIN
+<<la>>
+FOR ia IN 1 .. a
+LOOP
+total:= total + 1000;
+DECLARE
+ib INT:= 1;
+BEGIN
+WHILE ib <= b
+LOOP
+IF ib > blim THEN
+ITERATE la;
+END IF;
+ib:= ib + 1;
+total:= total + 1;
+END LOOP;
+END;
+END LOOP la;
+RETURN total;
+END;
+/
+SELECT f1(3,3,0), f1(3,3,1), f1(3,3,2), f1(3,3,3), f1(3,3,4) FROM DUAL;
+f1(3,3,0) f1(3,3,1) f1(3,3,2) f1(3,3,3) f1(3,3,4)
+3000 3003 3006 3009 3009
+DROP FUNCTION f1;
+# Testing CONTINUE statement
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+FOR i IN 1 .. a
+LOOP
+IF i=5 THEN
+CONTINUE;
+END IF;
+total:= total + 1;
+END LOOP;
+RETURN total;
+END;
+/
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+f1(3) f1(4) f1(5) f1(6)
+3 4 4 5
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+<<lj>>
+FOR j IN 1 .. 2
+LOOP
+FOR i IN 1 .. a
+LOOP
+IF i=5 THEN
+CONTINUE lj;
+END IF;
+total:= total + 1;
+END LOOP;
+END LOOP;
+RETURN total;
+END;
+/
+SELECT f1(3), f1(4), f1(5) FROM DUAL;
+f1(3) f1(4) f1(5)
+6 8 8
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+BEGIN
+<<lj>>
+FOR j IN 1 .. 2
+LOOP
+FOR i IN 1 .. a
+LOOP
+CONTINUE lj WHEN i=5;
+total:= total + 1;
+END LOOP;
+END LOOP;
+RETURN total;
+END;
+/
+SELECT f1(3), f1(4), f1(5) FROM DUAL;
+f1(3) f1(4) f1(5)
+6 8 8
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+total INT:= 0;
+i INT:= 1;
+BEGIN
+WHILE i <= a
+LOOP
+i:= i + 1;
+IF i=6 THEN
+CONTINUE;
+END IF;
+total:= total + 1;
+END LOOP;
+RETURN total;
+END;
+/
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+f1(3) f1(4) f1(5) f1(6)
+3 4 4 5
+DROP FUNCTION f1;
+#
+# Testing behaviour of unknown identifiers in EXIT and CONTINUE statements
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+LOOP
+EXIT WHEN unknown_ident IS NULL;
+END LOOP;
+END$$
+CALL p1;
+ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+<<label>>
+LOOP
+EXIT label WHEN unknown_ident IS NULL;
+END LOOP;
+END$$
+CALL p1;
+ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+LOOP
+CONTINUE WHEN unknown_ident IS NULL;
+END LOOP;
+END$$
+CALL p1;
+ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+BEGIN
+<<label>>
+LOOP
+CONTINUE label WHEN unknown_ident IS NULL;
+END LOOP;
+END$$
+CALL p1;
+ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
+DROP PROCEDURE p1;
+#
+# MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT
+#
+EXPLAIN EXTENDED SELECT sql%rowcount;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select SQL%ROWCOUNT AS "sql%rowcount"
+CREATE TABLE t1 AS SELECT SQL%ROWCOUNT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "SQL%ROWCOUNT" bigint(21) NOT NULL
+)
+DROP TABLE t1;
+#
+# UPDATE
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1
+AS
+BEGIN
+UPDATE t1 SET a=30;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+CREATE PROCEDURE p1
+AS
+BEGIN
+UPDATE t1 SET a=30;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+2
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# DELETE
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1
+AS
+BEGIN
+DELETE FROM t1;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+0
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+CREATE PROCEDURE p1
+AS
+BEGIN
+DELETE FROM t1;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+2
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# SELECT ... INTO var FROM ... - one row found
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+CREATE PROCEDURE p1
+AS
+va INT;
+BEGIN
+SELECT a INTO va FROM t1 LIMIT 1;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# SELECT ... INTO var FROM ... - no rows found
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1
+AS
+va INT;
+BEGIN
+SELECT a INTO va FROM t1;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+0
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+DROP PROCEDURE p1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1
+AS
+va INT;
+BEGIN
+SELECT a INTO va FROM t1;
+SELECT SQL%ROWCOUNT;
+EXCEPTION
+WHEN NO_DATA_FOUND THEN SELECT SQL%ROWCOUNT||' (EXCEPTION)';
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT||' (EXCEPTION)'
+0 (EXCEPTION)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# SELECT ... INTO var FROM ... - multiple rows found
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+CREATE PROCEDURE p1
+AS
+va INT:=1;
+BEGIN
+SELECT a INTO va FROM t1;
+SELECT SQL%ROWCOUNT;
+EXCEPTION
+WHEN TOO_MANY_ROWS THEN SELECT SQL%ROWCOUNT||' (EXCEPTION) va='||va;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT||' (EXCEPTION) va='||va
+1 (EXCEPTION) va=10
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# INSERT INTO t2 SELECT ...
+#
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+CREATE PROCEDURE p1
+AS
+BEGIN
+INSERT INTO t2 SELECT * FROM t1;
+SELECT SQL%ROWCOUNT;
+END;
+$$
+CALL p1();
+SQL%ROWCOUNT
+2
+DROP PROCEDURE p1;
+DROP TABLE t1, t2;
+#
+# End of MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT
+#
+#
+# MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+#
+#
+# Missing table
+#
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE;
+BEGIN
+NULL;
+END;
+$$
+CALL p1();
+ERROR 42S02: Table 'test.t1' doesn't exist
+DROP PROCEDURE p1;
+#
+# Missing column
+#
+CREATE TABLE t1 (b INT);
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE;
+BEGIN
+NULL;
+END;
+$$
+CALL p1();
+ERROR 42S22: Unknown column 'a' in 't1'
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# One %TYPE variable
+#
+CREATE TABLE t1 (a INT);
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE;
+BEGIN
+a:= 123;
+SELECT a;
+END;
+$$
+CALL p1();
+a
+123
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Two %TYPE variables, with a truncation warning on assignment
+#
+CREATE TABLE t1 (a TINYINT, b INT);
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE;
+b t1.b%TYPE;
+BEGIN
+a:= 200;
+b:= 200;
+SELECT a, b;
+END;
+$$
+CALL p1();
+a b
+127 200
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# %TYPE variables for fields with various attributes
+#
+CREATE TABLE t1 (
+id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
+a TINYINT NOT NULL,
+b INT NOT NULL,
+ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+UNIQUE(a)
+);
+CREATE PROCEDURE p1
+AS
+id t1.id%TYPE;
+a t1.a%TYPE;
+b t1.b%TYPE;
+ts t1.ts%TYPE;
+BEGIN
+SELECT id, a, b, ts;
+CREATE TABLE t2 AS SELECT id, a, b, ts;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+id a b ts
+NULL NULL NULL NULL
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "id" int(11) DEFAULT NULL,
+ "a" tinyint(4) DEFAULT NULL,
+ "b" int(11) DEFAULT NULL,
+ "ts" timestamp NULL DEFAULT NULL
+)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# %TYPE + virtual columns
+#
+CREATE TABLE t1 (
+a INT NOT NULL,
+b VARCHAR(32),
+c INT AS (a + 10) VIRTUAL,
+d VARCHAR(5) AS (left(b,5)) PERSISTENT
+);
+CREATE PROCEDURE p1
+AS
+c t1.c%TYPE;
+d t1.d%TYPE;
+BEGIN
+SELECT c, d;
+CREATE TABLE t2 AS SELECT c, d;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+c d
+NULL NULL
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "c" int(11) DEFAULT NULL,
+ "d" varchar(5) DEFAULT NULL
+)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# %TYPE + the ZEROFILL attribute
+#
+CREATE TABLE t1 (
+dz DECIMAL(10,3) ZEROFILL
+);
+CREATE PROCEDURE p1
+AS
+dzr t1.dz%TYPE := 10;
+dzt DECIMAL(10,3) ZEROFILL := 10;
+BEGIN
+SELECT dzr, dzt;
+CREATE TABLE t2 AS SELECT dzr,dzt;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+$$
+CALL p1();
+dzr dzt
+0000010.000 0000010.000
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "dzr" decimal(10,3) unsigned DEFAULT NULL,
+ "dzt" decimal(10,3) unsigned DEFAULT NULL
+)
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# Temporary tables shadow real tables for %TYPE purposes
+#
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('t1');
+CREATE TEMPORARY TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+a
+10
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE:=11;
+BEGIN
+CREATE TABLE t2 AS SELECT a;
+END;
+$$
+#
+# Should use INT(11) as %TYPE, as in the temporary table
+#
+CALL p1();
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" int(11) DEFAULT NULL
+)
+SELECT * FROM t2;
+a
+11
+DROP TABLE t2;
+SELECT * FROM t1;
+a
+10
+DROP TEMPORARY TABLE t1;
+SELECT * FROM t1;
+a
+t1
+#
+# Should use VARCHAR(10) as %TYPE, as in the real table
+#
+CALL p1();
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" varchar(10) DEFAULT NULL
+)
+SELECT * FROM t2;
+a
+11
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# t1.a%TYPE searches for "t1" in the current database
+#
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a INT);
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE:=11;
+BEGIN
+CREATE TABLE test.t2 AS SELECT a;
+END;
+$$
+#
+# This interprets t1.a%TYPE as VARCHAR(10), as in test.t1.a
+#
+USE test;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" varchar(10) DEFAULT NULL
+)
+DROP TABLE test.t2;
+#
+# This interprets t1.a%TYPE as INT, as in test1.t1.a
+#
+USE test1;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" int(11) DEFAULT NULL
+)
+DROP TABLE test.t2;
+#
+# Error if there is no an active database
+#
+DROP DATABASE test1;
+CALL test.p1();
+ERROR 3D000: No database selected
+USE test;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+#
+# A reference to a table in a non-existing database
+#
+CREATE PROCEDURE p1
+AS
+a test1.t1.a%TYPE;
+BEGIN
+CREATE TABLE t1 AS SELECT a;
+END;
+$$
+CALL p1;
+ERROR 42S02: Table 'test1.t1' doesn't exist
+DROP PROCEDURE p1;
+#
+# A reference to a table in a different database
+#
+CREATE TABLE t1(a INT);
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a VARCHAR(10));
+CREATE PROCEDURE p1
+AS
+a t1.a%TYPE;
+b test1.t1.a%TYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT a,b;
+END;
+$$
+CALL p1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" int(11) DEFAULT NULL,
+ "b" varchar(10) DEFAULT NULL
+)
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP DATABASE test1;
+DROP TABLE t1;
+#
+# Using a table before it appears in a %TYPE declaration + multiple %TYPE declarations
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 (a,b) VALUES (10,'b10');
+CREATE PROCEDURE p1
+AS
+BEGIN
+INSERT INTO t1 (a,b) VALUES (11, 'b11');
+SELECT * FROM t1;
+DECLARE
+va t1.a%TYPE:= 30;
+vb t1.b%TYPE:= 'b30';
+BEGIN
+INSERT INTO t1 (a,b) VALUES (12,'b12');
+SELECT * FROM t1;
+INSERT INTO t1 (a,b) VALUES (va, vb);
+SELECT * FROM t1;
+END;
+DECLARE
+va t1.a%TYPE:= 40;
+vb t1.b%TYPE:= 'b40';
+BEGIN
+INSERT INTO t1 (a,b) VALUES (va,vb);
+SELECT * FROM t1;
+END;
+END;
+$$
+CALL p1;
+a b
+10 b10
+11 b11
+a b
+10 b10
+11 b11
+12 b12
+a b
+10 b10
+11 b11
+12 b12
+30 b30
+a b
+10 b10
+11 b11
+12 b12
+30 b30
+40 b40
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# %TYPE variables + TABLE vs VIEW
+#
+CREATE TABLE t1 (
+bit6 BIT(6),
+bit7 BIT(7),
+bit8 BIT(8),
+i1 TINYINT,
+i2 SMALLINT,
+i3 MEDIUMINT,
+i4 INT,
+i8 BIGINT,
+ff FLOAT,
+fd DOUBLE,
+cc CHAR(10),
+cv VARCHAR(10),
+cvu VARCHAR(10) CHARACTER SET utf8,
+t1 TINYTEXT,
+t2 TEXT,
+t3 MEDIUMTEXT,
+t4 LONGTEXT,
+enum1 ENUM('a','b','c'),
+set1 SET('a','b','c'),
+blob1 TINYBLOB,
+blob2 BLOB,
+blob3 MEDIUMBLOB,
+blob4 LONGBLOB,
+yy YEAR,
+dd DATE,
+tm0 TIME,
+tm3 TIME(3),
+tm6 TIME(6),
+dt0 DATETIME,
+dt3 DATETIME(3),
+dt6 DATETIME(6),
+ts0 TIMESTAMP,
+ts3 TIMESTAMP(3),
+ts6 TIMESTAMP(6),
+dc100 DECIMAL(10,0),
+dc103 DECIMAL(10,3),
+dc209 DECIMAL(20,9)
+);
+CREATE PROCEDURE p1(command enum('create','select'))
+AS
+bit6 t1.bit6%TYPE := 0x30;
+bit7 t1.bit7%TYPE := 0x41;
+bit8 t1.bit8%TYPE := 0x7E;
+i1 t1.i1%TYPE := 11;
+i2 t1.i2%TYPE := 12;
+i3 t1.i3%TYPE := 13;
+i4 t1.i4%TYPE := 14;
+i8 t1.i8%TYPE := 18;
+ff t1.ff%TYPE := 21;
+fd t1.fd%TYPE := 22;
+cc t1.cc%TYPE := 'char';
+cv t1.cv%TYPE := 'varchar';
+cvu t1.cvu%TYPE := 'varcharu8';
+t1 t1.t1%TYPE := 'text1';
+t2 t1.t2%TYPE := 'text2';
+t3 t1.t3%TYPE := 'text3';
+t4 t1.t4%TYPE := 'text4';
+enum1 t1.enum1%TYPE := 'b';
+set1 t1.set1%TYPE := 'a,c';
+blob1 t1.blob1%TYPE := 'blob1';
+blob2 t1.blob2%TYPE := 'blob2';
+blob3 t1.blob3%TYPE := 'blob3';
+blob4 t1.blob4%TYPE := 'blob4';
+yy t1.yy%TYPE := 2001;
+dd t1.dd%TYPE := '2001-01-01';
+tm0 t1.tm0%TYPE := '00:00:01';
+tm3 t1.tm3%TYPE := '00:00:03.333';
+tm6 t1.tm6%TYPE := '00:00:06.666666';
+dt0 t1.dt0%TYPE := '2001-01-01 00:00:01';
+dt3 t1.dt3%TYPE := '2001-01-03 00:00:01.333';
+dt6 t1.dt6%TYPE := '2001-01-06 00:00:01.666666';
+ts0 t1.ts0%TYPE := '2002-01-01 00:00:01';
+ts3 t1.ts3%TYPE := '2002-01-03 00:00:01.333';
+ts6 t1.ts6%TYPE := '2002-01-06 00:00:01.666666';
+dc100 t1.dc100%TYPE := 10;
+dc103 t1.dc103%TYPE := 10.123;
+dc209 t1.dc209%TYPE := 10.123456789;
+BEGIN
+CASE
+WHEN command='create' THEN
+CREATE TABLE t2 AS SELECT
+bit6, bit7, bit8,
+i1,i2,i3,i4,i8,
+ff,fd, dc100, dc103, dc209,
+cc,cv,cvu,
+t1,t2,t3,t4,
+enum1, set1,
+blob1, blob2, blob3, blob4,
+dd, yy,
+tm0, tm3, tm6,
+dt0, dt3, dt6,
+ts0, ts3, ts6;
+WHEN command='select' THEN
+SELECT
+bit6, bit7, bit8,
+i1,i2,i3,i4,i8,
+ff,fd, dc100, dc103, dc209,
+cc,cv,cvu,
+t1,t2,t3,t4,
+enum1, set1,
+blob1, blob2, blob3, blob4,
+dd, yy,
+tm0, tm3, tm6,
+dt0, dt3, dt6,
+ts0, ts3, ts6;
+END CASE;
+END;
+$$
+#
+# TABLE
+#
+CALL p1('create');
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "bit6" bit(6) DEFAULT NULL,
+ "bit7" bit(7) DEFAULT NULL,
+ "bit8" bit(8) DEFAULT NULL,
+ "i1" tinyint(4) DEFAULT NULL,
+ "i2" smallint(6) DEFAULT NULL,
+ "i3" mediumint(9) DEFAULT NULL,
+ "i4" int(11) DEFAULT NULL,
+ "i8" bigint(20) DEFAULT NULL,
+ "ff" float DEFAULT NULL,
+ "fd" double DEFAULT NULL,
+ "dc100" decimal(10,0) DEFAULT NULL,
+ "dc103" decimal(10,3) DEFAULT NULL,
+ "dc209" decimal(20,9) DEFAULT NULL,
+ "cc" varchar(10) DEFAULT NULL,
+ "cv" varchar(10) DEFAULT NULL,
+ "cvu" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "t1" tinytext DEFAULT NULL,
+ "t2" text DEFAULT NULL,
+ "t3" mediumtext DEFAULT NULL,
+ "t4" longtext DEFAULT NULL,
+ "enum1" varchar(1) DEFAULT NULL,
+ "set1" varchar(5) DEFAULT NULL,
+ "blob1" tinyblob DEFAULT NULL,
+ "blob2" longblob DEFAULT NULL,
+ "blob3" mediumblob DEFAULT NULL,
+ "blob4" longblob DEFAULT NULL,
+ "dd" datetime DEFAULT NULL,
+ "yy" year(4) DEFAULT NULL,
+ "tm0" time DEFAULT NULL,
+ "tm3" time(3) DEFAULT NULL,
+ "tm6" time(6) DEFAULT NULL,
+ "dt0" datetime DEFAULT NULL,
+ "dt3" datetime(3) DEFAULT NULL,
+ "dt6" datetime(6) DEFAULT NULL,
+ "ts0" timestamp NULL DEFAULT NULL,
+ "ts3" timestamp(3) NULL DEFAULT NULL,
+ "ts6" timestamp(6) NULL DEFAULT NULL
+)
+SELECT * FROM t2;
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01 00:00:00
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+DROP TABLE t2;
+CALL p1('select');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def bit6 bit6 16 6 1 Y 32 0 63
+def bit7 bit7 16 7 1 Y 32 0 63
+def bit8 bit8 16 8 1 Y 32 0 63
+def i1 i1 1 4 2 Y 32768 0 63
+def i2 i2 2 6 2 Y 32768 0 63
+def i3 i3 9 9 2 Y 32768 0 63
+def i4 i4 3 11 2 Y 32768 0 63
+def i8 i8 8 20 2 Y 32768 0 63
+def ff ff 4 12 2 Y 32768 31 63
+def fd fd 5 22 2 Y 32768 31 63
+def dc100 dc100 246 11 2 Y 32768 0 63
+def dc103 dc103 246 12 6 Y 32768 3 63
+def dc209 dc209 246 22 12 Y 32768 9 63
+def cc cc 254 10 4 Y 0 0 8
+def cv cv 253 10 7 Y 0 0 8
+def cvu cvu 253 10 9 Y 0 0 8
+def t1 t1 252 255 5 Y 16 0 8
+def t2 t2 252 65535 5 Y 16 0 8
+def t3 t3 252 16777215 5 Y 16 0 8
+def t4 t4 252 4294967295 5 Y 16 0 8
+def enum1 enum1 254 1 1 Y 256 0 8
+def set1 set1 254 5 3 Y 2048 0 8
+def blob1 blob1 252 255 5 Y 144 0 63
+def blob2 blob2 252 4294967295 5 Y 144 0 63
+def blob3 blob3 252 16777215 5 Y 144 0 63
+def blob4 blob4 252 4294967295 5 Y 144 0 63
+def dd dd 12 19 19 Y 128 0 63
+def yy yy 13 4 4 Y 32864 0 63
+def tm0 tm0 11 10 8 Y 128 0 63
+def tm3 tm3 11 14 12 Y 128 3 63
+def tm6 tm6 11 17 15 Y 128 6 63
+def dt0 dt0 12 19 19 Y 128 0 63
+def dt3 dt3 12 23 23 Y 128 3 63
+def dt6 dt6 12 26 26 Y 128 6 63
+def ts0 ts0 7 19 19 Y 9376 0 63
+def ts3 ts3 7 23 23 Y 160 3 63
+def ts6 ts6 7 26 26 Y 160 6 63
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01 00:00:00
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+#
+# VIEW
+#
+ALTER TABLE t1 RENAME t0;
+CREATE VIEW t1 AS SELECT * FROM t0;
+CALL p1('create');
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "bit6" bit(6) DEFAULT NULL,
+ "bit7" bit(7) DEFAULT NULL,
+ "bit8" bit(8) DEFAULT NULL,
+ "i1" tinyint(4) DEFAULT NULL,
+ "i2" smallint(6) DEFAULT NULL,
+ "i3" mediumint(9) DEFAULT NULL,
+ "i4" int(11) DEFAULT NULL,
+ "i8" bigint(20) DEFAULT NULL,
+ "ff" float DEFAULT NULL,
+ "fd" double DEFAULT NULL,
+ "dc100" decimal(10,0) DEFAULT NULL,
+ "dc103" decimal(10,3) DEFAULT NULL,
+ "dc209" decimal(20,9) DEFAULT NULL,
+ "cc" varchar(10) DEFAULT NULL,
+ "cv" varchar(10) DEFAULT NULL,
+ "cvu" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "t1" tinytext DEFAULT NULL,
+ "t2" text DEFAULT NULL,
+ "t3" mediumtext DEFAULT NULL,
+ "t4" longtext DEFAULT NULL,
+ "enum1" varchar(1) DEFAULT NULL,
+ "set1" varchar(5) DEFAULT NULL,
+ "blob1" tinyblob DEFAULT NULL,
+ "blob2" longblob DEFAULT NULL,
+ "blob3" mediumblob DEFAULT NULL,
+ "blob4" longblob DEFAULT NULL,
+ "dd" datetime DEFAULT NULL,
+ "yy" year(4) DEFAULT NULL,
+ "tm0" time DEFAULT NULL,
+ "tm3" time(3) DEFAULT NULL,
+ "tm6" time(6) DEFAULT NULL,
+ "dt0" datetime DEFAULT NULL,
+ "dt3" datetime(3) DEFAULT NULL,
+ "dt6" datetime(6) DEFAULT NULL,
+ "ts0" timestamp NULL DEFAULT NULL,
+ "ts3" timestamp(3) NULL DEFAULT NULL,
+ "ts6" timestamp(6) NULL DEFAULT NULL
+)
+SELECT * FROM t2;
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01 00:00:00
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+DROP TABLE t2;
+CALL p1('select');
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def bit6 bit6 16 6 1 Y 32 0 63
+def bit7 bit7 16 7 1 Y 32 0 63
+def bit8 bit8 16 8 1 Y 32 0 63
+def i1 i1 1 4 2 Y 32768 0 63
+def i2 i2 2 6 2 Y 32768 0 63
+def i3 i3 9 9 2 Y 32768 0 63
+def i4 i4 3 11 2 Y 32768 0 63
+def i8 i8 8 20 2 Y 32768 0 63
+def ff ff 4 12 2 Y 32768 31 63
+def fd fd 5 22 2 Y 32768 31 63
+def dc100 dc100 246 11 2 Y 32768 0 63
+def dc103 dc103 246 12 6 Y 32768 3 63
+def dc209 dc209 246 22 12 Y 32768 9 63
+def cc cc 254 10 4 Y 0 0 8
+def cv cv 253 10 7 Y 0 0 8
+def cvu cvu 253 10 9 Y 0 0 8
+def t1 t1 252 255 5 Y 16 0 8
+def t2 t2 252 65535 5 Y 16 0 8
+def t3 t3 252 16777215 5 Y 16 0 8
+def t4 t4 252 4294967295 5 Y 16 0 8
+def enum1 enum1 254 1 1 Y 256 0 8
+def set1 set1 254 5 3 Y 2048 0 8
+def blob1 blob1 252 255 5 Y 144 0 63
+def blob2 blob2 252 4294967295 5 Y 144 0 63
+def blob3 blob3 252 16777215 5 Y 144 0 63
+def blob4 blob4 252 4294967295 5 Y 144 0 63
+def dd dd 12 19 19 Y 128 0 63
+def yy yy 13 4 4 Y 32864 0 63
+def tm0 tm0 11 10 8 Y 128 0 63
+def tm3 tm3 11 14 12 Y 128 3 63
+def tm6 tm6 11 17 15 Y 128 6 63
+def dt0 dt0 12 19 19 Y 128 0 63
+def dt3 dt3 12 23 23 Y 128 3 63
+def dt6 dt6 12 26 26 Y 128 6 63
+def ts0 ts0 7 19 19 Y 160 0 63
+def ts3 ts3 7 23 23 Y 160 3 63
+def ts6 ts6 7 26 26 Y 160 6 63
+bit6 0
+bit7 A
+bit8 ~
+i1 11
+i2 12
+i3 13
+i4 14
+i8 18
+ff 21
+fd 22
+dc100 10
+dc103 10.123
+dc209 10.123456789
+cc char
+cv varchar
+cvu varcharu8
+t1 text1
+t2 text2
+t3 text3
+t4 text4
+enum1 b
+set1 a,c
+blob1 blob1
+blob2 blob2
+blob3 blob3
+blob4 blob4
+dd 2001-01-01 00:00:00
+yy 2001
+tm0 00:00:01
+tm3 00:00:03.333
+tm6 00:00:06.666666
+dt0 2001-01-01 00:00:01
+dt3 2001-01-03 00:00:01.333
+dt6 2001-01-06 00:00:01.666666
+ts0 2002-01-01 00:00:01
+ts3 2002-01-03 00:00:01.333
+ts6 2002-01-06 00:00:01.666666
+DROP VIEW t1;
+DROP TABLE t0;
+DROP PROCEDURE p1;
+#
+# VIEW with subqueries
+#
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,1),(20,2),(30,3),(40,4);
+SELECT AVG(a) FROM t1;
+AVG(a)
+25.0000
+CREATE VIEW v1 AS SELECT a,1 as b FROM t1 WHERE a>(SELECT AVG(a) FROM t1) AND b>(SELECT 1);
+SELECT * FROM v1;
+a b
+30 1
+40 1
+CREATE PROCEDURE p1
+AS
+a v1.a%TYPE := 10;
+b v1.b%TYPE := 1;
+BEGIN
+SELECT a,b;
+END;
+$$
+CALL p1;
+a b
+10 1
+DROP PROCEDURE p1;
+CREATE FUNCTION f1 RETURN INT
+AS
+a v1.a%TYPE := 10;
+b v1.b%TYPE := 1;
+BEGIN
+RETURN a+b;
+END;
+$$
+SELECT f1();
+f1()
+11
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
+#
+# %TYPE variables + INFORMATION_SCHEMA
+#
+CREATE PROCEDURE p1
+AS
+tables_table_name INFORMATION_SCHEMA.TABLES.TABLE_NAME%TYPE;
+tables_table_rows INFORMATION_SCHEMA.TABLES.TABLE_ROWS%TYPE;
+processlist_info INFORMATION_SCHEMA.PROCESSLIST.INFO%TYPE;
+processlist_info_binary INFORMATION_SCHEMA.PROCESSLIST.INFO_BINARY%TYPE;
+BEGIN
+CREATE TABLE t1 AS SELECT
+tables_table_name,
+tables_table_rows,
+processlist_info,
+processlist_info_binary;
+END;
+$$
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "tables_table_name" varchar(64) CHARACTER SET utf8 DEFAULT NULL,
+ "tables_table_rows" bigint(21) unsigned DEFAULT NULL,
+ "processlist_info" longtext CHARACTER SET utf8 DEFAULT NULL,
+ "processlist_info_binary" blob DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# %TYPE + Table structure change
+# Data type for both a0 and a1 is chosen in the very beginning
+#
+CREATE PROCEDURE p1
+AS
+a0 t1.a%TYPE;
+BEGIN
+ALTER TABLE t1 MODIFY a VARCHAR(10); -- This does not affect a1
+DECLARE
+a1 t1.a%TYPE;
+BEGIN
+CREATE TABLE t2 AS SELECT a0, a1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+END;
+END
+$$
+CREATE TABLE t1 (a INT);
+CALL p1;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a0" int(11) DEFAULT NULL,
+ "a1" int(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# %TYPE in parameters
+#
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (b SMALLINT);
+CREATE PROCEDURE p1(a t1.a%TYPE, b test1.t1.b%TYPE)
+AS
+BEGIN
+CREATE TABLE t2 AS SELECT a, b;
+END;
+$$
+CALL p1('test', 123);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE "t2" (
+ "a" varchar(10) DEFAULT NULL,
+ "b" smallint(6) DEFAULT NULL
+)
+SELECT * FROM t2;
+a b
+test 123
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE test1.t1;
+DROP DATABASE test1;
+DROP TABLE t1;
+#
+# %TYPE in a stored function variables and arguments
+#
+CREATE TABLE t1 (a INT);
+SET sql_mode=ORACLE;
+CREATE FUNCTION f1 (prm t1.a%TYPE) RETURN INT
+AS
+a t1.a%TYPE:= prm;
+BEGIN
+RETURN a;
+END;
+$$
+SELECT f1(20);
+f1(20)
+20
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# %TYPE in function RETURN clause is not supported yet
+#
+CREATE FUNCTION f1 RETURN t1.a%TYPE
+AS
+BEGIN
+RETURN 0;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1.a%TYPE
+AS
+BEGIN
+RETURN 0;
+END' at line 1
+#
+# End of MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+#
+#
+# MDEV-12089 sql_mode=ORACLE: Understand optional routine name after the END keyword
+#
+CREATE FUNCTION f1 RETURN INT AS
+BEGIN
+RETURN 10;
+END f1;
+$$
+DROP FUNCTION f1;
+CREATE FUNCTION test.f1 RETURN INT AS
+BEGIN
+RETURN 10;
+END test.f1;
+$$
+DROP FUNCTION f1;
+CREATE FUNCTION test.f1 RETURN INT AS
+BEGIN
+RETURN 10;
+END test2.f1;
+$$
+ERROR HY000: END identifier 'test2.f1' does not match 'test.f1'
+CREATE FUNCTION test.f1 RETURN INT AS
+BEGIN
+RETURN 10;
+END test.f2;
+$$
+ERROR HY000: END identifier 'test.f2' does not match 'test.f1'
+CREATE FUNCTION f1 RETURN INT AS
+BEGIN
+RETURN 10;
+END test.f2;
+$$
+ERROR HY000: END identifier 'test.f2' does not match 'test.f1'
+CREATE FUNCTION f1 RETURN INT AS
+BEGIN
+RETURN 10;
+END test2.f1;
+$$
+ERROR HY000: END identifier 'test2.f1' does not match 'test.f1'
+CREATE PROCEDURE p1 AS
+BEGIN
+NULL;
+END p1;
+$$
+DROP PROCEDURE p1;
+CREATE PROCEDURE test.p1 AS
+BEGIN
+NULL;
+END test.p1;
+$$
+DROP PROCEDURE p1;
+CREATE PROCEDURE test.p1 AS
+BEGIN
+NULL;
+END test2.p1;
+$$
+ERROR HY000: END identifier 'test2.p1' does not match 'test.p1'
+CREATE PROCEDURE test.p1 AS
+BEGIN
+NULL;
+END test.p2;
+$$
+ERROR HY000: END identifier 'test.p2' does not match 'test.p1'
+CREATE PROCEDURE p1 AS
+BEGIN
+NULL;
+END test.p2;
+$$
+ERROR HY000: END identifier 'test.p2' does not match 'test.p1'
+CREATE PROCEDURE p1 AS
+BEGIN
+NULL;
+END test2.p1;
+$$
+ERROR HY000: END identifier 'test2.p1' does not match 'test.p1'
+#
+# MDEV-12107 sql_mode=ORACLE: Inside routines the CALL keywoard is optional
+#
+CREATE OR REPLACE PROCEDURE p1(a INT) AS
+BEGIN
+SELECT 'This is p1' AS "comment";
+END;
+/
+CREATE OR REPLACE PROCEDURE p2 AS
+BEGIN
+SELECT 'This is p2' AS "comment";
+END;
+/
+BEGIN
+p1(10);
+p2;
+test.p1(10);
+test.p2;
+END;
+/
+comment
+This is p1
+comment
+This is p2
+comment
+This is p1
+comment
+This is p2
+CREATE PROCEDURE p3 AS
+BEGIN
+p1(10);
+p2;
+test.p1(10);
+test.p2;
+END
+/
+CALL p3;
+comment
+This is p1
+comment
+This is p2
+comment
+This is p1
+comment
+This is p2
+DROP PROCEDURE p3;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+SELECT SQL%ROWCOUNT;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def SQL%ROWCOUNT 8 21 1 N 32897 0 63
+SQL%ROWCOUNT
+0
diff --git a/mysql-test/suite/compat/oracle/r/trigger.result b/mysql-test/suite/compat/oracle/r/trigger.result
new file mode 100644
index 00000000000..f77a56546fa
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/trigger.result
@@ -0,0 +1,100 @@
+set sql_mode=ORACLE;
+:NEW.a := 1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a := 1' at line 1
+:OLD.a := 1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a := 1' at line 1
+:OLa.a := 1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a := 1' at line 1
+SELECT :NEW.a;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a' at line 1
+SELECT :OLD.a;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a' at line 1
+SELECT :OLa.a;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a' at line 1
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW NEW.a:= 10;
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+a
+10
+DROP TRIGGER tr1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW :NEW.a:= 10;
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+a
+10
+DROP TRIGGER tr1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+IF :NEW.a IS NULL
+THEN
+:NEW.a:= 10;
+END IF;
+END;
+/
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+a
+10
+DROP TRIGGER tr1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+IF :OLD.a IS NULL
+THEN
+:NEW.a:= 10;
+END IF;
+END;
+/
+INSERT INTO t1 VALUES (NULL);
+UPDATE t1 SET a=NULL;
+SELECT * FROM t1;
+a
+10
+DROP TRIGGER tr1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT, c INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+DECLARE
+cnt INT := 0;
+BEGIN
+IF :NEW.a IS NULL THEN cnt:=cnt+1; END IF;
+IF :NEW.b IS NULL THEN cnt:=cnt+1; END IF;
+IF :NEW.c IS NULL THEN :NEW.c:=cnt; END IF;
+END;
+/
+INSERT INTO t1 VALUES ();
+INSERT INTO t1 VALUES (1, NULL, NULL);
+INSERT INTO t1 VALUES (NULL, 1, NULL);
+INSERT INTO t1 VALUES (1, 1, NULL);
+SELECT * FROM t1;
+a b c
+NULL NULL 2
+1 NULL 1
+NULL 1 1
+1 1 0
+DROP TABLE t1;
+#
+# MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+#
+CREATE TABLE t1 (a INT, b INT, total INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+DECLARE
+va t1.a%TYPE:= :NEW.a;
+vb t1.b%TYPE:= :NEW.b;
+BEGIN
+:NEW.total:= va + vb;
+END;
+$$
+INSERT INTO t1 (a,b) VALUES (10, 20);
+SELECT * FROM t1;
+a b total
+10 20 30
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/truncate.result b/mysql-test/suite/compat/oracle/r/truncate.result
new file mode 100644
index 00000000000..f04ce09a4f8
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/truncate.result
@@ -0,0 +1,10 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10588 sql_mode=ORACLE: TRUNCATE TABLE t1 [ {DROP|REUSE} STORAGE ]
+#
+CREATE TABLE t1 (a INT);
+TRUNCATE TABLE t1 REUSE STORAGE;
+TRUNCATE TABLE t1 DROP STORAGE;
+DROP TABLE t1;
+CREATE TABLE reuse (reuse INT);
+DROP TABLE reuse;
diff --git a/mysql-test/suite/compat/oracle/r/type_blob.result b/mysql-test/suite/compat/oracle/r/type_blob.result
new file mode 100644
index 00000000000..fe0a78e6ceb
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_blob.result
@@ -0,0 +1,8 @@
+SET sql_mode=ORACLE;
+CREATE TABLE t1 (a BLOB);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" longblob DEFAULT NULL
+)
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/type_clob.result b/mysql-test/suite/compat/oracle/r/type_clob.result
new file mode 100644
index 00000000000..f96572ea277
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_clob.result
@@ -0,0 +1,15 @@
+SET sql_mode=ORACLE;
+CREATE TABLE clob (clob INT);
+SHOW CREATE TABLE clob;
+Table Create Table
+clob CREATE TABLE "clob" (
+ "clob" int(11) DEFAULT NULL
+)
+DROP TABLE clob;
+CREATE TABLE t1 (a CLOB);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" longtext DEFAULT NULL
+)
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/type_date.result b/mysql-test/suite/compat/oracle/r/type_date.result
new file mode 100644
index 00000000000..0989fc593d2
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_date.result
@@ -0,0 +1,8 @@
+SET sql_mode=ORACLE;
+CREATE TABLE t1 (a DATE);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" datetime DEFAULT NULL
+)
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/type_number.result b/mysql-test/suite/compat/oracle/r/type_number.result
new file mode 100644
index 00000000000..c0848fdccf9
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_number.result
@@ -0,0 +1,15 @@
+SET sql_mode=ORACLE;
+CREATE TABLE t1 (a NUMBER);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" double DEFAULT NULL
+)
+DROP TABLE t1;
+CREATE TABLE t1 (a NUMBER(10,2));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" decimal(10,2) DEFAULT NULL
+)
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/type_raw.result b/mysql-test/suite/compat/oracle/r/type_raw.result
new file mode 100644
index 00000000000..1698c96d5b4
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_raw.result
@@ -0,0 +1,15 @@
+SET sql_mode=ORACLE;
+CREATE TABLE raw (raw INT);
+SHOW CREATE TABLE raw;
+Table Create Table
+raw CREATE TABLE "raw" (
+ "raw" int(11) DEFAULT NULL
+)
+DROP TABLE raw;
+CREATE TABLE t1 (a RAW(10));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" varbinary(10) DEFAULT NULL
+)
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/type_varchar.result b/mysql-test/suite/compat/oracle/r/type_varchar.result
new file mode 100644
index 00000000000..906e16867cd
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_varchar.result
@@ -0,0 +1,9 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-11275 sql_mode=ORACLE: CAST(..AS VARCHAR(N))
+#
+SELECT CAST(123 AS VARCHAR(10)) FROM DUAL;
+CAST(123 AS VARCHAR(10))
+123
+SELECT CAST(123 AS VARCHAR) FROM DUAL;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') FROM DUAL' at line 1
diff --git a/mysql-test/suite/compat/oracle/r/type_varchar2.result b/mysql-test/suite/compat/oracle/r/type_varchar2.result
new file mode 100644
index 00000000000..5030cfbaa0a
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/type_varchar2.result
@@ -0,0 +1,23 @@
+SET sql_mode=ORACLE;
+CREATE TABLE varchar2 (varchar2 INT);
+SHOW CREATE TABLE varchar2;
+Table Create Table
+varchar2 CREATE TABLE "varchar2" (
+ "varchar2" int(11) DEFAULT NULL
+)
+DROP TABLE varchar2;
+CREATE TABLE t1 (a VARCHAR2(10));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "a" varchar(10) DEFAULT NULL
+)
+DROP TABLE t1;
+#
+# MDEV-11275 sql_mode=ORACLE: CAST(..AS VARCHAR(N))
+#
+SELECT CAST(123 AS VARCHAR2(10)) FROM DUAL;
+CAST(123 AS VARCHAR2(10))
+123
+SELECT CAST(123 AS VARCHAR2) FROM DUAL;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') FROM DUAL' at line 1
diff --git a/mysql-test/suite/compat/oracle/r/variables.result b/mysql-test/suite/compat/oracle/r/variables.result
new file mode 100644
index 00000000000..a7067d7b3fd
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/variables.result
@@ -0,0 +1,39 @@
+SET sql_mode=oracle;
+#
+# MDEV-10411 Providing compatibility for basic PL/SQL constructs
+# Part 6: Assignment operator
+#
+max_sort_length:=1030;
+SELECT @@max_sort_length;
+@@max_sort_length
+1030
+max_sort_length:=DEFAULT;
+#
+# Testing that SP variables shadow global variables in assignments
+#
+CREATE PROCEDURE p1
+AS
+BEGIN
+max_sort_length:=1030;
+DECLARE
+max_sort_length INT DEFAULT 1031;
+BEGIN
+SELECT @@max_sort_length, max_sort_length;
+max_sort_length:=1032;
+SELECT @@max_sort_length, max_sort_length;
+END;
+SELECT @@max_sort_length;
+max_sort_length:= DEFAULT;
+END;
+$$
+CALL p1();
+@@max_sort_length max_sort_length
+1030 1031
+@@max_sort_length max_sort_length
+1030 1032
+@@max_sort_length
+1030
+DROP PROCEDURE p1;
+#
+# End of MDEV-10411 Providing compatibility for basic PL/SQL constructs (part 6)
+#
diff --git a/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test b/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test
new file mode 100644
index 00000000000..996ef574413
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test
@@ -0,0 +1,37 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10801 sql_mode: dynamic SQL placeholders
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+SET @a=10, @b=20;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (?,?)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:a,:b)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:aaa,:bbb)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"a",:"b")';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:"aaa",:"bbb")';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:1,:2)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:222,:111)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:0,:65535)';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'INSERT INTO t1 VALUES (:65535,:0)';
+EXECUTE stmt USING @a, @b;
+SELECT * FROM t1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/binlog_stm_sp.test b/mysql-test/suite/compat/oracle/t/binlog_stm_sp.test
new file mode 100644
index 00000000000..065c43eb274
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/binlog_stm_sp.test
@@ -0,0 +1,196 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:=100;
+ rec.b:=200;
+ INSERT INTO t1 VALUES (rec.a,rec.b);
+ INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.a:=NULL;
+ INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+ INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+ INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+ INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.b:=NULL;
+ INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # Testing ROW fields in LIMIT
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT:= 1;
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 1;
+ INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+ INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+--echo #
+--echo # MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec t1%ROWTYPE;
+BEGIN
+ rec.a:=100;
+ rec.b:=200;
+ SELECT rec=ROW(100,200) AS true1, ROW(100,200)=rec AS true2;
+ INSERT INTO t1 VALUES (rec.a,rec.b);
+ INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.a:=NULL;
+ INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+ INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+ INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+ INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.b:=NULL;
+ INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # MDEV-12291 Allow ROW variables as SELECT INTO targets
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+ SELECT * INTO rec1 FROM t1;
+ INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ SELECT * INTO rec1 FROM t1;
+ INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10, 'b10');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ rec1 cur1%ROWTYPE;
+BEGIN
+ SELECT * INTO rec1 FROM t1;
+ INSERT INTO t2 VALUES (rec1.a, rec1.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/compat/oracle/t/exception.test b/mysql-test/suite/compat/oracle/t/exception.test
new file mode 100644
index 00000000000..6448a6ef627
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/exception.test
@@ -0,0 +1,457 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # sql_mode=ORACLE: Predefined exceptions: TOO_MANY_ROWS, NO_DATA_FOUND, DUP_VAL_ON_INDEX
+--echo #
+
+--echo #
+--echo # Testing NO_DATA_FOUND and TOO_MANY_ROWS
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1 LIMIT lim;
+EXCEPTION
+ WHEN TOO_MANY_ROWS THEN res:='--- too_many_rows cought ---';
+ WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought ---';
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL p1(0, @res);
+SELECT @res;
+CALL p1(2, @res);
+SELECT @res;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing DUP_VAL_ON_INDEX
+--echo #
+
+CREATE TABLE t1 (a INT PRIMARY KEY);
+DELIMITER $$;
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+BEGIN
+ INSERT INTO t1 VALUES (10);
+ INSERT INTO t1 VALUES (10);
+EXCEPTION
+ WHEN DUP_VAL_ON_INDEX THEN res:='--- dup_val_on_index cought ---';
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL p1(@res);
+SELECT @res;
+SELECT * FROM t1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions
+--echo #
+
+--echo #
+--echo # RAISE outside of an SP context
+--echo #
+
+--error ER_SP_COND_MISMATCH
+RAISE NO_DATA_FOUND;
+--error ER_SP_COND_MISMATCH
+RAISE INVALID_CURSOR;
+--error ER_SP_COND_MISMATCH
+RAISE DUP_VAL_ON_INDEX;
+--error ER_SP_COND_MISMATCH
+RAISE TOO_MANY_ROWS;
+
+--error ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER
+RAISE;
+
+
+--echo #
+--echo # RAISE for an undefinite exception
+--echo #
+
+DELIMITER $$;
+--error ER_SP_COND_MISMATCH
+CREATE PROCEDURE p1
+AS
+BEGIN
+ RAISE xxx;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # RAISE for predefined exceptions
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ RAISE no_data_found;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ RAISE invalid_cursor;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_CURSOR_NOT_OPEN
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ RAISE dup_val_on_index;
+END;
+$$
+DELIMITER ;$$
+--error ER_DUP_ENTRY
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ raise too_many_rows;
+END;
+$$
+DELIMITER ;$$
+--error ER_TOO_MANY_ROWS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # RAISE with no exception name (resignal)
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+BEGIN
+ RAISE;
+END;
+$$
+DELIMITER ;$$
+--error ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER
+CALL p1();
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1(lim INT)
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1 LIMIT lim;
+EXCEPTION
+ WHEN TOO_MANY_ROWS THEN RAISE;
+ WHEN NO_DATA_FOUND THEN RAISE;
+END;
+$$
+DELIMITER ;$$
+CALL p1(0);
+--error ER_TOO_MANY_ROWS
+CALL p1(2);
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1(lim INT)
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1 LIMIT lim;
+EXCEPTION
+ WHEN OTHERS THEN RAISE;
+END;
+$$
+DELIMITER ;$$
+CALL p1(0);
+--error ER_TOO_MANY_ROWS
+CALL p1(2);
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT;
+ CURSOR c IS SELECT a FROM t1;
+BEGIN
+ FETCH c INTO a;
+EXCEPTION
+ WHEN INVALID_CURSOR THEN RAISE;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_CURSOR_NOT_OPEN
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT;
+ CURSOR c IS SELECT a FROM t1;
+BEGIN
+ FETCH c INTO a;
+EXCEPTION
+ WHEN OTHERS THEN RAISE;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_CURSOR_NOT_OPEN
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing that warning-alike errors are caught by OTHERS
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+ a INT:=10;
+BEGIN
+ SELECT a INTO a FROM t1;
+ RETURN 'OK';
+EXCEPTION
+ WHEN OTHERS THEN RETURN 'Exception';
+END;
+$$
+DELIMITER ;$$
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions
+--echo #
+
+
+--echo #
+--echo # MDEV-10587 sql_mode=ORACLE: User defined exceptions
+--echo #
+
+--echo #
+--echo # Checking that duplicate WHEN clause is not allowed
+--echo #
+
+DELIMITER $$;
+--error ER_SP_DUP_HANDLER
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+ e EXCEPTION;
+BEGIN
+ RETURN 'Got no exceptions';
+EXCEPTION
+ WHEN e THEN RETURN 'Got exception e';
+ WHEN e THEN RETURN 'Got exception e';
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Checking that raised user exceptions are further caught by name
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+ e EXCEPTION;
+ f EXCEPTION;
+BEGIN
+ IF c = 'e' THEN RAISE e; END IF;
+ IF c = 'f' THEN RAISE f; END IF;
+ RETURN 'Got no exceptions';
+EXCEPTION
+ WHEN e THEN RETURN 'Got exception e';
+END;
+$$
+DELIMITER ;$$
+SELECT f1('');
+SELECT f1('e');
+--error ER_SIGNAL_EXCEPTION
+SELECT f1('f');
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Checking that raised user exceptions are further caught by OTHERS
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+ e EXCEPTION;
+ f EXCEPTION;
+BEGIN
+ IF c = 'e' THEN RAISE e; END IF;
+ IF c = 'f' THEN RAISE f; END IF;
+ RETURN 'Got no exceptions';
+EXCEPTION
+ WHEN OTHERS THEN RETURN 'Got some exception';
+END;
+$$
+DELIMITER ;$$
+SELECT f1('');
+SELECT f1('e');
+SELECT f1('f');
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Checking that 'WHEN e .. WHEN f' does not produce ER_SP_DUP_HANDLER
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+ e EXCEPTION;
+ f EXCEPTION;
+ a VARCHAR(64):='';
+BEGIN
+ BEGIN
+ IF c = 'e' THEN RAISE e; END IF;
+ IF c = 'f' THEN RAISE f; END IF;
+ EXCEPTION
+ WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE e; END;
+ WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE f; END;
+ END;
+ RETURN 'Got no exceptions';
+EXCEPTION
+ WHEN OTHERS THEN RETURN a || 'Got EXCEPTION2/OTHERS;';
+END;
+$$
+DELIMITER ;$$
+SELECT f1('');
+SELECT f1('e');
+SELECT f1('f');
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Checking that resignaled user exceptions are further caught by name
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+ e EXCEPTION;
+ f EXCEPTION;
+ a VARCHAR(64):='';
+BEGIN
+ BEGIN
+ IF c = 'e' THEN RAISE e; END IF;
+ IF c = 'f' THEN RAISE f; END IF;
+ EXCEPTION
+ WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE; END;
+ WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE; END;
+ END;
+ RETURN 'Got no exceptions';
+EXCEPTION
+ WHEN e THEN RETURN a || 'Got EXCEPTION2/e;';
+END;
+$$
+DELIMITER ;$$
+SELECT f1('');
+SELECT f1('e');
+--error ER_SIGNAL_EXCEPTION
+SELECT f1('f');
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Checking that resignaled user exceptions are further caught by OTHERS
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(c VARCHAR) RETURN VARCHAR
+AS
+ e EXCEPTION;
+ f EXCEPTION;
+ a VARCHAR(64):='';
+BEGIN
+ BEGIN
+ IF c = 'e' THEN RAISE e; END IF;
+ IF c = 'f' THEN RAISE f; END IF;
+ EXCEPTION
+ WHEN e THEN BEGIN a:='Got EXCEPTION1/e; '; RAISE; END;
+ WHEN f THEN BEGIN a:='Got EXCEPTION1/f; '; RAISE; END;
+ END;
+ RETURN 'Got no exceptions';
+EXCEPTION
+ WHEN OTHERS THEN RETURN a || 'Got EXCEPTION2/OTHERS;';
+END;
+$$
+DELIMITER ;$$
+SELECT f1('');
+SELECT f1('e');
+SELECT f1('f');
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # End of MDEV-10587 sql_mode=ORACLE: User defined exceptions
+--echo #
+
+--echo #
+--echo # MDEV-12088 sql_mode=ORACLE: Do not require BEGIN..END in multi-statement exception handlers in THEN clause
+--echo #
+CREATE TABLE t1 (a INT PRIMARY KEY);
+INSERT INTO t1 VALUES (10),(20),(30);
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT) AS
+BEGIN
+ INSERT INTO t1 (a) VALUES (a);
+EXCEPTION
+ WHEN DUP_VAL_ON_INDEX THEN
+ a:= a+1;
+ INSERT INTO t1 VALUES (a);
+ WHEN OTHERS THEN
+ NULL;
+ NULL;
+END;
+$$
+DELIMITER ;$$
+CALL p1(30);
+SELECT * FROM t1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/func_case.test b/mysql-test/suite/compat/oracle/t/func_case.test
new file mode 100644
index 00000000000..d5e0d650975
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/func_case.test
@@ -0,0 +1,9 @@
+#
+# Testing CASE and its abbreviations
+#
+
+SET sql_mode=ORACLE;
+
+SELECT NVL(NULL, 'a'), NVL('a', 'b');
+
+SELECT NVL2(NULL, 'a', 'b'), NVL2('a', 'b', 'c');
diff --git a/mysql-test/suite/compat/oracle/t/func_concat.test b/mysql-test/suite/compat/oracle/t/func_concat.test
new file mode 100644
index 00000000000..e1d8a5c477f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/func_concat.test
@@ -0,0 +1,116 @@
+#
+# Testing CONCAT with null values
+#
+
+SET sql_mode=ORACLE;
+
+EXPLAIN EXTENDED SELECT 'a'||'b'||'c';
+EXPLAIN EXTENDED SELECT CONCAT('a'||'b'||'c');
+
+SELECT '' || '';
+SELECT '' || 'b';
+SELECT '' || NULL;
+SELECT 'a' || '';
+SELECT 'a' || 'b';
+SELECT 'a' || NULL;
+SELECT NULL || '';
+SELECT NULL || 'b';
+SELECT NULL || NULL;
+
+SELECT '' || '' || '';
+SELECT '' || '' || 'c';
+SELECT '' || '' || NULL;
+SELECT '' || 'b' || '';
+SELECT '' || 'b' || 'c';
+SELECT '' || 'b' || NULL;
+SELECT '' || NULL || '';
+SELECT '' || NULL || 'c';
+SELECT '' || NULL || NULL;
+
+SELECT 'a' || '' || '';
+SELECT 'a' || '' || 'c';
+SELECT 'a' || '' || NULL;
+SELECT 'a' || 'b' || '';
+SELECT 'a' || 'b' || 'c';
+SELECT 'a' || 'b' || NULL;
+SELECT 'a' || NULL || '';
+SELECT 'a' || NULL || 'c';
+SELECT 'a' || NULL || NULL;
+
+SELECT NULL || '' || '';
+SELECT NULL || '' || 'c';
+SELECT NULL || '' || NULL;
+SELECT NULL || 'b' || '';
+SELECT NULL || 'b' || 'c';
+SELECT NULL || 'b' || NULL;
+SELECT NULL || NULL || '';
+SELECT NULL || NULL || 'c';
+SELECT NULL || NULL || NULL;
+
+CREATE TABLE t1 (a VARCHAR(10), b VARCHAR(10), c VARCHAR(10));
+
+INSERT INTO t1 VALUES ('', '', '');
+INSERT INTO t1 VALUES ('', '', 'c');
+INSERT INTO t1 VALUES ('', '', NULL);
+INSERT INTO t1 VALUES ('', 'b', '');
+INSERT INTO t1 VALUES ('', 'b', 'c');
+INSERT INTO t1 VALUES ('', 'b', NULL);
+INSERT INTO t1 VALUES ('', NULL, '');
+INSERT INTO t1 VALUES ('', NULL, 'c');
+INSERT INTO t1 VALUES ('', NULL, NULL);
+
+INSERT INTO t1 VALUES ('a', '', '');
+INSERT INTO t1 VALUES ('a', '', 'c');
+INSERT INTO t1 VALUES ('a', '', NULL);
+INSERT INTO t1 VALUES ('a', 'b', '');
+INSERT INTO t1 VALUES ('a', 'b', 'c');
+INSERT INTO t1 VALUES ('a', 'b', NULL);
+INSERT INTO t1 VALUES ('a', NULL, '');
+INSERT INTO t1 VALUES ('a', NULL, 'c');
+INSERT INTO t1 VALUES ('a', NULL, NULL);
+
+INSERT INTO t1 VALUES (NULL, '', '');
+INSERT INTO t1 VALUES (NULL, '', 'c');
+INSERT INTO t1 VALUES (NULL, '', NULL);
+INSERT INTO t1 VALUES (NULL, 'b', '');
+INSERT INTO t1 VALUES (NULL, 'b', 'c');
+INSERT INTO t1 VALUES (NULL, 'b', NULL);
+INSERT INTO t1 VALUES (NULL, NULL, '');
+INSERT INTO t1 VALUES (NULL, NULL, 'c');
+INSERT INTO t1 VALUES (NULL, NULL, NULL);
+
+SELECT LENGTH(a||b||c), a||b||c FROM t1 ORDER BY a,b,c;
+SELECT LENGTH(CONCAT(a||b||c)), CONCAT(a||b||c) FROM t1 ORDER BY a,b,c;
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12478 CONCAT function inside view casts values incorrectly with Oracle sql_mode
+--echo #
+
+SET sql_mode=ORACLE;
+CREATE VIEW v1 AS SELECT 'foo'||NULL||'bar' AS test;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+SET sql_mode=DEFAULT;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+DROP VIEW v1;
+
+SET sql_mode=DEFAULT;
+CREATE VIEW v1 AS SELECT CONCAT('foo',NULL,'bar') AS test;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+SET sql_mode=ORACLE;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+DROP VIEW v1;
+
+SET sql_mode=DEFAULT;
+CREATE VIEW v1 AS SELECT '0'||'1' AS test;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+SET sql_mode=ORACLE;
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+DROP VIEW v1;
diff --git a/mysql-test/suite/compat/oracle/t/func_decode.test b/mysql-test/suite/compat/oracle/t/func_decode.test
new file mode 100644
index 00000000000..ae05cb2c3d1
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/func_decode.test
@@ -0,0 +1,21 @@
+SET sql_mode=ORACLE;
+
+--error ER_PARSE_ERROR
+SELECT DECODE(10);
+--error ER_PARSE_ERROR
+SELECT DECODE(10,10);
+
+SELECT DECODE(10,10,'x10');
+SELECT DECODE(11,10,'x10');
+
+SELECT DECODE(10,10,'x10','def');
+SELECT DECODE(11,10,'x10','def');
+
+SELECT DECODE(10,10,'x10',11,'x11','def');
+SELECT DECODE(11,10,'x10',11,'x11','def');
+SELECT DECODE(12,10,'x10',11,'x11','def');
+
+EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
+
+CREATE TABLE decode (decode int);
+DROP TABLE decode;
diff --git a/mysql-test/suite/compat/oracle/t/func_length.test b/mysql-test/suite/compat/oracle/t/func_length.test
new file mode 100644
index 00000000000..7b76d33a02f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/func_length.test
@@ -0,0 +1,18 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-12783 sql_mode=ORACLE: Functions LENGTH() and LENGTHB()
+--echo #
+#
+# Testing LENGTH / LENGTHB
+#
+# LENGTH : return the length of char
+# LENGTHB : return the length of byte
+
+
+SELECT LENGTH(null), LENGTH('a'), LENGTH(123);
+SELECT LENGTHB(null), LENGTHB('a'), LENGTHB(123);
+
+SELECT LENGTH(_utf8 0xC39F), LENGTH(CHAR(14844588 USING utf8));
+SELECT LENGTHB(_utf8 0xC39F), LENGTHB(CHAR(14844588 USING utf8));
+EXPLAIN EXTENDED SELECT LENGTH('a'), LENGTHB('a');
diff --git a/mysql-test/suite/compat/oracle/t/func_misc.test b/mysql-test/suite/compat/oracle/t/func_misc.test
new file mode 100644
index 00000000000..c5b42134f89
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/func_misc.test
@@ -0,0 +1,346 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
+--echo #
+
+--echo #
+--echo # Using SQLCODE and SQLERRM outside of an SP
+--echo #
+
+--error ER_BAD_FIELD_ERROR
+SELECT SQLCODE;
+
+--error ER_BAD_FIELD_ERROR
+SELECT SQLERRM;
+
+CREATE TABLE t1 (SQLCODE INT, SQLERRM VARCHAR(10));
+INSERT INTO t1 VALUES (10, 'test');
+SELECT SQLCODE, SQLERRM FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # Normal SQLCODE and SQLERRM usage
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(stmt VARCHAR)
+AS
+BEGIN
+ EXECUTE IMMEDIATE stmt;
+ SELECT 'Error1: ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+ WHEN OTHERS THEN
+ SELECT 'Error2: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1('SELECT 1');
+CALL p1('xxx');
+CALL p1('SELECT 1');
+DROP PROCEDURE p1;
+
+--echo #
+--echo # SQLCODE and SQLERRM hidden by local variables
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ sqlcode INT:= 10;
+ sqlerrm VARCHAR(64) := 'test';
+BEGIN
+ SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ sqlcode INT;
+ sqlerrm VARCHAR(64);
+BEGIN
+ SQLCODE:= 10;
+ sqlerrm:= 'test';
+ SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # SQLCODE and SQLERRM hidden by parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(sqlcode INT, sqlerrm VARCHAR)
+AS
+BEGIN
+ SELECT 'Error: ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1(10, 'test');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # SQLCODE and SQLERRM in CREATE..SELECT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ CREATE TABLE t1 AS SELECT SQLCODE, SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # SQLCODE and SQLERRM in EXPLAIN EXTENDED SELECT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ EXPLAIN EXTENDED SELECT SQLCode, SQLErrm;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+
+--echo #
+--echo # Warning-alike errors in stored functions
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1;
+ RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+ WHEN NO_DATA_FOUND THEN
+ RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1;
+ RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+ WHEN OTHERS THEN
+ RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Warning-alike errors in stored procedures
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1;
+ res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+ WHEN NO_DATA_FOUND THEN
+ res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1(@a);
+SELECT @a;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ SELECT a INTO a FROM t1;
+ res:= 'No exception ' || SQLCODE || ' ' || SQLERRM;
+EXCEPTION
+ WHEN OTHERS THEN
+ res:= 'Exception ' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+CALL p1(@a);
+SELECT @a;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # SQLCODE and SQLERRM are cleared on RETURN
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+ a INT:=10;
+BEGIN
+ SELECT a INTO a FROM t1;
+ RETURN 'Value=' || a;
+EXCEPTION
+ WHEN NO_DATA_FOUND THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+ a VARCHAR(128);
+BEGIN
+ RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+SELECT f1() FROM DUAL;
+SELECT f2() FROM DUAL;
+DROP TABLE t1;
+DROP FUNCTION f2;
+DROP FUNCTION f1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN VARCHAR
+AS
+ a INT:=10;
+BEGIN
+ SELECT a INTO a FROM t1;
+ RETURN 'Value=' || a;
+EXCEPTION
+ WHEN OTHERS THEN RETURN 'Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+ a VARCHAR(128);
+BEGIN
+ RETURN f1() || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+SELECT f1() FROM DUAL;
+SELECT f2() FROM DUAL;
+DROP TABLE t1;
+DROP FUNCTION f2;
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # SQLCODE and SQLERRM are cleared on a return from a PROCEDURE
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+ a INT:=10;
+BEGIN
+ SELECT a INTO a FROM t1;
+ res:='Value=' || a;
+EXCEPTION
+ WHEN NO_DATA_FOUND THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+ res VARCHAR(128);
+BEGIN
+ CALL p1(res);
+ RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+SELECT f2() FROM DUAL;
+DROP FUNCTION f2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1(res OUT VARCHAR)
+AS
+ a INT:=10;
+BEGIN
+ SELECT a INTO a FROM t1;
+ res:='Value=' || a;
+EXCEPTION
+ WHEN OTHERS THEN res:='Exception|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+CREATE FUNCTION f2 RETURN VARCHAR
+AS
+ res VARCHAR(128);
+BEGIN
+ CALL p1(res);
+ RETURN res || '|' || SQLCODE || ' ' || SQLERRM;
+END;
+$$
+DELIMITER ;$$
+SELECT f2() FROM DUAL;
+DROP FUNCTION f2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of MDEV-10578 sql_mode=ORACLE: SP control functions SQLCODE, SQLERRM
+--echo #
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+DELIMITER $$;
+BEGIN
+ SELECT SQLCODE;
+END
+$$
+DELIMITER ;$$
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/suite/compat/oracle/t/misc.test b/mysql-test/suite/compat/oracle/t/misc.test
new file mode 100644
index 00000000000..d939b20f8a0
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/misc.test
@@ -0,0 +1,10 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-12086 sql_mode=ORACLE: allow SELECT UNIQUE as a synonym for SELECT DISTINCT
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20),(20),(30),(30),(30);
+SELECT UNIQUE a FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/ps.test b/mysql-test/suite/compat/oracle/t/ps.test
new file mode 100644
index 00000000000..08bb957c33f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/ps.test
@@ -0,0 +1,266 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10801 sql_mode: dynamic SQL placeholders
+--echo #
+
+SET @a=10, @b=20;
+PREPARE stmt FROM 'SELECT ?,?';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :a,:b';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :aaa,:bbb';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :"a",:"b"';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :"aaa",:"bbb"';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :1,:2';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :222,:111';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :0,:65535';
+EXECUTE stmt USING @a, @b;
+PREPARE stmt FROM 'SELECT :65535,:0';
+EXECUTE stmt USING @a, @b;
+
+--echo #
+--echo # MDEV-10709 Expressions as parameters to Dynamic SQL
+--echo #
+
+--echo #
+--echo # Testing disallowed expressions in USING
+--echo #
+
+PREPARE stmt FROM 'SELECT :1 FROM DUAL';
+--error ER_PARSE_ERROR
+EXECUTE stmt USING (SELECT 1);
+DEALLOCATE PREPARE stmt;
+
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+BEGIN
+ RETURN 'test';
+END;
+$$
+DELIMITER ;$$
+PREPARE stmt FROM 'SELECT ? FROM DUAL';
+--error ER_SUBQUERIES_NOT_SUPPORTED
+EXECUTE stmt USING f1();
+DEALLOCATE PREPARE stmt;
+DROP FUNCTION f1;
+
+--echo #
+--echo # Using a user variable as a EXECUTE..USING out parameter
+--echo #
+
+DELIMITER /;
+CREATE PROCEDURE p1(a OUT INT)
+AS
+BEGIN
+ a:= 10;
+END;
+/
+DELIMITER ;/
+SET @a=1;
+CALL p1(@a);
+SELECT @a;
+SET @a=2;
+PREPARE stmt FROM 'CALL p1(?)';
+EXECUTE stmt USING @a;
+SELECT @a;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using an SP variable as a EXECUTE..USING out parameter
+--echo #
+
+DELIMITER /;
+CREATE PROCEDURE p1 (a OUT INT)
+AS
+BEGIN
+ a:=10;
+END;
+/
+CREATE PROCEDURE p2 (a OUT INT)
+AS
+BEGIN
+ PREPARE stmt FROM 'CALL p1(?)';
+ EXECUTE stmt USING a;
+END;
+/
+DELIMITER ;/
+SET @a= 1;
+CALL p2(@a);
+SELECT @a;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using a trigger field as a EXECUTE..USING out parameter
+--echo #
+DELIMITER /;
+CREATE PROCEDURE p1 (a OUT INT)
+AS
+BEGIN
+ a:= 10;
+END;
+/
+DELIMITER ;/
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW CALL p1(:NEW.a);
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing re-prepare on a table metadata update between PREPARE and EXECUTE
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER /;
+CREATE PROCEDURE p1(a IN INT)
+AS
+BEGIN
+ INSERT INTO t1 VALUES (a);
+END;
+/
+DELIMITER ;/
+PREPARE stmt FROM 'CALL p1(?)';
+EXECUTE stmt USING 10;
+SELECT * FROM t1;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW NEW.a:=NEW.a+1;
+EXECUTE stmt USING 20;
+SELECT * FROM t1;
+DEALLOCATE PREPARE stmt;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of MDEV-10709 Expressions as parameters to Dynamic SQL
+--echo #
+
+--echo #
+--echo # MDEV-10585 EXECUTE IMMEDIATE statement
+--echo #
+
+--echo #
+--echo # Testing disallowed expressions in USING
+--echo #
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING (SELECT 1);
+
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+BEGIN
+ RETURN 'test';
+END;
+$$
+DELIMITER ;$$
+--error ER_SUBQUERIES_NOT_SUPPORTED
+EXECUTE IMMEDIATE 'SELECT ? FROM DUAL' USING f1();
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Testing simple expressions
+--echo #
+
+EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING 10;
+
+
+--echo #
+--echo # MDEV-10866 Extend PREPARE and EXECUTE IMMEDIATE to understand expressions
+--echo #
+
+--echo #
+--echo # Testing erroneous and diallowed prepare source
+--echo #
+
+--error ER_CANT_AGGREGATE_2COLLATIONS
+EXECUTE IMMEDIATE _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL';
+--error ER_CANT_AGGREGATE_2COLLATIONS
+PREPARE stmt FROM _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL';
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE (SELECT 'SELECT 1');
+--error ER_PARSE_ERROR
+PREPARE stmt FROM (SELECT 'SELECT 1');
+
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE a;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM a;
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE NULL;
+--error ER_PARSE_ERROR
+PREPARE stmt FROM NULL;
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE COALESCE(NULL);
+--error ER_PARSE_ERROR
+PREPARE stmt FROM COALESCE(NULL);
+
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN VARCHAR
+AS
+BEGIN
+ RETURN 't1';
+END;
+$$
+DELIMITER ;$$
+--error ER_SUBQUERIES_NOT_SUPPORTED
+EXECUTE IMMEDIATE f1();
+--error ER_SUBQUERIES_NOT_SUPPORTED
+PREPARE stmt FROM f1();
+DROP FUNCTION f1;
+
+--echo #
+--echo # Testing user variables in prepare source
+--echo #
+
+SET @table_name='DUAL';
+EXECUTE IMMEDIATE 'SELECT 1 AS a FROM ' || @table_name;
+PREPARE stmt FROM 'SELECT 1 AS a FROM ' || @table_name;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+--echo #
+--echo # Testing SP parameters and variables in prepare source
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(table_name VARCHAR)
+AS
+BEGIN
+ EXECUTE IMMEDIATE 'SELECT 1 AS c FROM '|| table_name;
+END;
+$$
+DELIMITER ;$$
+CALL p1('DUAL');
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ table_name VARCHAR(64):='DUAL';
+BEGIN
+ EXECUTE IMMEDIATE 'SELECT 1 AS c FROM ' || table_name;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # End of MDEV-10866 Extend PREPARE and EXECUTE IMMEDIATE to understand expressions
+--echo #
diff --git a/mysql-test/suite/compat/oracle/t/sequence.test b/mysql-test/suite/compat/oracle/t/sequence.test
new file mode 100644
index 00000000000..719c4bcd45b
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sequence.test
@@ -0,0 +1,43 @@
+--source include/have_binlog_format_row.inc
+
+SET sql_mode=ORACLE;
+
+CREATE SEQUENCE s1;
+SHOW CREATE SEQUENCE s1;
+SELECT s1.currval;
+SELECT s1.nextval;
+SELECT s1.nextval;
+SELECT s1.nextval;
+EXPLAIN EXTENDED SELECT s1.nextval;
+SELECT nextval(s1);
+EXPLAIN EXTENDED SELECT s1.currval;
+SELECT lastval(s1);
+DROP SEQUENCE s1;
+
+
+CREATE SEQUENCE s1;
+CREATE VIEW v1 AS SELECT s1.nextval AS a;
+SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1';
+SELECT * FROM v1;
+SHOW CREATE VIEW v1;
+DROP VIEW v1;
+DROP SEQUENCE s1;
+
+
+CREATE SEQUENCE s1;
+CREATE VIEW v1 AS SELECT s1.currval AS a;
+SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1';
+SELECT * FROM v1;
+SHOW CREATE VIEW v1;
+DROP VIEW v1;
+DROP SEQUENCE s1;
+
+--echo #
+--echo # MDEV-12533 sql_mode=ORACLE: Add support for database qualified sequence names in NEXTVAL and CURRVAL
+--echo #
+CREATE SEQUENCE s1;
+SELECT test.s1.nextval;
+SELECT test.s1.currval;
+SELECT .s1.nextval;
+SELECT .s1.currval;
+DROP SEQUENCE s1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-anonymous.test b/mysql-test/suite/compat/oracle/t/sp-anonymous.test
new file mode 100644
index 00000000000..ac61e8ace2e
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-anonymous.test
@@ -0,0 +1,244 @@
+--source include/have_innodb.inc
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10655 Anonymous blocks
+--echo #
+
+--echo # Testing BEGIN NOT ATOMIC with no declarations
+DELIMITER /;
+BEGIN NOT ATOMIC
+ SELECT 1 AS a;
+END
+/
+DELIMITER ;/
+
+--echo # Testing BEGIN NOT ATOMIC with declarations
+--echo # DECLARE starts a new block and thus must be followed by BEGIN .. END
+DELIMITER /;
+BEGIN NOT ATOMIC
+ DECLARE
+ i INT DEFAULT 5;
+ x INT DEFAULT 10;
+ BEGIN
+ <<label>>
+ WHILE i > 3 LOOP
+ i:= i - 1;
+ SELECT i;
+ END LOOP label;
+ END;
+END
+/
+DELIMITER ;/
+
+
+--echo # Anonymous blocks with no declarations and no exceptions
+
+DELIMITER $$;
+BEGIN
+ SELECT 1 AS a;
+END
+$$
+DELIMITER ;$$
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+BEGIN
+ INSERT INTO t1 VALUES(20);
+ INSERT INTO t1 VALUES(30);
+ ROLLBACK;
+END;
+$$
+DELIMITER ;$$
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+BEGIN
+ INSERT INTO t1 VALUES(20);
+ INSERT INTO t1 VALUES(30);
+END;
+$$
+DELIMITER ;$$
+ROLLBACK;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+BEGIN
+ INSERT INTO t1 VALUES(20);
+ INSERT INTO t1 VALUES(30);
+ COMMIT;
+END;
+$$
+DELIMITER ;$$
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+BEGIN
+ INSERT INTO t1 VALUES(20);
+ INSERT INTO t1 VALUES(30);
+END;
+$$
+DELIMITER ;$$
+COMMIT;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+--error ER_DUP_ENTRY
+BEGIN
+ INSERT INTO t1 VALUES(20);
+ INSERT INTO t1 VALUES(20);
+END;
+$$
+DELIMITER ;$$
+COMMIT;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+--echo # Anonymous blocks with no declarations, with exceptions
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+BEGIN
+ INSERT INTO t1 VALUES(20);
+ INSERT INTO t1 VALUES(20);
+EXCEPTION
+ WHEN DUP_VAL_ON_INDEX THEN NULL;
+END;
+$$
+DELIMITER ;$$
+COMMIT;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+--echo # Anonymous blocks with declarations, with no exceptions
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+DECLARE
+ a20 INT:=20;
+ a30 INT:=30;
+BEGIN
+ INSERT INTO t1 VALUES(a20);
+ INSERT INTO t1 VALUES(a30);
+ ROLLBACK;
+END;
+$$
+DELIMITER ;$$
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+DECLARE
+ a20 INT:=20;
+ a30 INT:=30;
+BEGIN
+ INSERT INTO t1 VALUES(a20);
+ INSERT INTO t1 VALUES(a30);
+END;
+$$
+DELIMITER ;$$
+ROLLBACK;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+DECLARE
+ a20 INT:=20;
+ a30 INT:=30;
+BEGIN
+ INSERT INTO t1 VALUES(a20);
+ INSERT INTO t1 VALUES(a30);
+ COMMIT;
+END;
+$$
+DELIMITER ;$$
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+DECLARE
+ a20 INT:=20;
+ a30 INT:=30;
+BEGIN
+ INSERT INTO t1 VALUES(a20);
+ INSERT INTO t1 VALUES(a30);
+END;
+$$
+DELIMITER ;$$
+COMMIT;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
+
+
+--echo # Anonymous blocks with declarations, with exceptions
+
+SET AUTOCOMMIT=OFF;
+CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+DECLARE
+ a20 INT:=20;
+BEGIN
+ INSERT INTO t1 VALUES(a20);
+ INSERT INTO t1 VALUES(a20);
+EXCEPTION
+ WHEN DUP_VAL_ON_INDEX THEN NULL;
+END;
+$$
+DELIMITER ;$$
+COMMIT;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET AUTOCOMMIT=DEFAULT;
diff --git a/mysql-test/suite/compat/oracle/t/sp-code.test b/mysql-test/suite/compat/oracle/t/sp-code.test
new file mode 100644
index 00000000000..9a1f64e54b4
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-code.test
@@ -0,0 +1,1057 @@
+-- source include/have_debug.inc
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # Testing exceptions in the top-level blocks
+--echo #
+
+--echo # No HANDLER declarations, no exceptions
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+AS
+BEGIN
+ RETURN 10;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1();
+DROP FUNCTION f1;
+
+--echo # No HANDLER declarations, no code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 ()
+IS
+BEGIN
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo # No HANDLER declarations, no code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+EXCEPTION
+ WHEN 1002 THEN v:=225;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # No HANDLER declarations, some code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=224;
+EXCEPTION
+ WHEN 1002 THEN v:=225;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # Some HANDLER declarations, no code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=123;
+ END;
+BEGIN
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # Some HANDLER declarations, no code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=123;
+ END;
+BEGIN
+EXCEPTION
+ WHEN 1002 THEN v:=225;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # Some HANDLER declarations, some code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=123;
+ END;
+BEGIN
+ v:=223;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # Some HANDLER declarations, some code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT VARCHAR2(20))
+IS
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=123;
+ END;
+ CONTINUE HANDLER FOR 1001
+ BEGIN
+ SET v=223;
+ END;
+BEGIN
+ v:= 1;
+EXCEPTION
+ WHEN 1002 THEN SET v=225;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing EXCEPTIONS in internal blocks
+--echo #
+
+--echo # No HANDLER declarations, no code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ BEGIN
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # No HANDLER declarations, no code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ BEGIN
+ EXCEPTION
+ WHEN 20002 THEN v:=335;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # No HANDLER declarations, some code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ BEGIN
+ v:=223;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # No HANDLER declarations, some code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ BEGIN
+ v:=223;
+ EXCEPTION
+ WHEN 20002 THEN v:=335;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # Some HANDLER declarations, no code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ DECLARE
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=323;
+ END;
+ BEGIN
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # Some HANDLER declarations, no code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ DECLARE
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=323;
+ END;
+ BEGIN
+ EXCEPTION
+ WHEN 20002 THEN v:=335;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # Some HANDLER declarations, some code, no exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ DECLARE
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=323;
+ END;
+ BEGIN
+ v:= 324;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo # Some HANDLER declarations, some code, some exceptions
+DELIMITER /;
+CREATE PROCEDURE p1 (v IN OUT INT)
+IS
+BEGIN
+ v:=123;
+ DECLARE
+ EXIT HANDLER FOR 1000
+ BEGIN
+ v:=323;
+ END;
+ BEGIN
+ v:= 324;
+ EXCEPTION WHEN 2002 THEN v:= 325;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Testing EXIT statement
+--echo #
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ LOOP
+ i:= i + 1;
+ IF i >= 5 THEN
+ EXIT;
+ END IF;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ LOOP
+ i:= i + 1;
+ EXIT WHEN i >=5;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ LOOP
+ BEGIN
+ i:= i + 1;
+ IF i >= 5 THEN
+ EXIT;
+ END IF;
+ EXCEPTION
+ WHEN OTHERS THEN i:= 1000;
+ END;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE PROCEDURE p1(a IN OUT INT)
+IS
+ i INT := 0;
+BEGIN
+ LOOP
+ LOOP
+ BEGIN
+ i:= i + 1;
+ IF i >=5 THEN
+ EXIT;
+ END IF;
+ EXCEPTION
+ WHEN OTHERS THEN a:=1000;
+ END;
+ END LOOP;
+ i:= i + 100;
+ EXIT;
+ END LOOP;
+ a:= i;
+EXCEPTION
+ WHEN OTHERS THEN a:=11;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+set @v= 10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # Testing RETURN in procedures
+DELIMITER /;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+ IF a < 10 THEN
+ BEGIN
+ a:= a + 1;
+ RETURN;
+ END;
+ END IF;
+ a:= 200;
+EXCEPTION
+ WHEN OTHERS THEN
+ BEGIN
+ a:= 100;
+ RETURN;
+ END;
+END;
+/
+DELIMITER ;/
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+--echo # Testing FOR loop statement
+DELIMITER /;
+CREATE FUNCTION f1 (a INT, b INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ FOR i IN 1 .. a
+ LOOP
+ total:= total + i;
+ IF i = b THEN
+ EXIT;
+ END IF;
+ END LOOP;
+ RETURN total;
+END
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(3, 100) FROM DUAL;
+SELECT f1(3, 2) FROM DUAL;
+DROP FUNCTION f1;
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT, b INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ FOR i IN REVERSE a..1
+ LOOP
+ total:= total + i;
+ IF i = b THEN
+ EXIT;
+ END IF;
+ END LOOP;
+ RETURN total;
+END
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(3, 100) FROM DUAL;
+SELECT f1(3, 2) FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing labeled FOR LOOP statement
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT, limita INT, b INT, limitb INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ <<la>>
+ FOR ia IN 1 .. a
+ LOOP
+ total:= total + 1000;
+ <<lb>>
+ FOR ib IN 1 .. b
+ LOOP
+ total:= total + 1;
+ EXIT lb WHEN ib = limitb;
+ EXIT la WHEN ia = limita;
+ END LOOP lb;
+ END LOOP la;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(2, 1, 2, 2) FROM DUAL;
+SELECT f1(2, 2, 2, 2) FROM DUAL;
+SELECT f1(2, 3, 2, 3) FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing labeled ITERATE in a labeled FOR LOOP
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ <<li>>
+ FOR i IN 1 .. a
+ LOOP
+ total:= total + 1000;
+ IF i = 5 THEN
+ ITERATE li;
+ END IF;
+ total:= total + 1;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ <<li>>
+ FOR i IN 1 .. a
+ LOOP
+ FOR j IN 1 .. 2
+ LOOP
+ total:= total + 1000;
+ IF i = 5 THEN
+ ITERATE li;
+ END IF;
+ total:= total + 1;
+ END LOOP;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ <<lj>>
+ FOR j IN 1 .. 2
+ LOOP
+ <<li>>
+ FOR i IN 1 .. a
+ LOOP
+ total:= total + 1000;
+ IF i = 5 THEN
+ ITERATE li;
+ END IF;
+ total:= total + 1;
+ END LOOP;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing CONTINUE statement
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ FOR i IN 1 .. a
+ LOOP
+ CONTINUE WHEN i=5;
+ total:= total + 1;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SHOW FUNCTION CODE f1;
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+DROP FUNCTION f1;
+
+--echo #
+--echo # Start of MDEV-10597 Cursors with parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(arg_value_a VARCHAR, arg_value_b VARCHAR,
+ arg_pattern_a VARCHAR, arg_pattern_b VARCHAR)
+AS
+ v_a VARCHAR(10);
+ v_b VARCHAR(20);
+ CURSOR c (p_value_a VARCHAR,
+ p_value_b VARCHAR,
+ p_pattern_a VARCHAR,
+ p_pattern_b VARCHAR,
+ p_limit_a INT,
+ p_limit_b INT,
+ p_unused TEXT) IS
+ (SELECT p_value_a, p_value_b FROM DUAL
+ WHERE p_value_a LIKE p_pattern_a LIMIT p_limit_a)
+ UNION
+ (SELECT p_value_b, p_value_a FROM DUAL
+ WHERE p_value_b LIKE p_pattern_b LIMIT p_limit_b);
+BEGIN
+ OPEN c(arg_value_a, (SELECT arg_value_b),
+ arg_pattern_a, arg_pattern_b, 100, 101, 'x');
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT v_a, v_b;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('aaa','bbb','aaa','bbb');
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # End of MDEV-10597 Cursors with parameters
+--echo #
+
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN INT
+AS
+ a ROW(a INT, b INT);
+BEGIN
+ a.b:= 200;
+ RETURN a.b;
+END;
+$$
+DELIMITER ;$$
+SHOW FUNCTION CODE f1;
+SELECT f1();
+DROP FUNCTION f1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+ rec:= ROW(10,20.123456,30.123,'test');
+ SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ ROW(10,20.123456,30.123,'test');
+BEGIN
+ SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+ rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+ rec1:= ROW(10,20.123456,30.123,'test');
+ rec2:= rec1;
+ SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ ROW(10,20.123456,30.123,'test');
+ rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) := rec1;
+BEGIN
+ SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+--echo #
+--echo # MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ rec1.a:= 10;
+ rec1.b:= 'bbb';
+ rec1.c:= 10e2;
+ rec1.d:= 10.12;
+ rec1.c:= rec1.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1,rec2 cur1%ROWTYPE;
+ rec3 cur2%ROWTYPE;
+ BEGIN
+ rec1.a:= 10;
+ rec1.b:= 'bbb';
+ END;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-10581 sql_mode=ORACLE: Explicit cursor FOR LOOP
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur0 IS SELECT 10 AS a, 'b0' AS b;
+ CURSOR cur1 IS SELECT 10 AS a, 'b0' AS b;
+ CURSOR cur2 IS SELECT 10 AS a, 'b0' AS b;
+BEGIN
+ FOR rec1 IN cur1
+ LOOP
+ SELECT rec1.a, rec1.b;
+ rec1.a:= 11;
+ rec1.b:= 'b1';
+ SELECT rec1.a, rec1.b;
+ END LOOP;
+ FOR rec0 IN cur0
+ LOOP
+ rec0.a:= 10;
+ rec0.b:='b0';
+ END LOOP;
+ FOR rec2 IN cur2
+ LOOP
+ rec2.a:= 10;
+ rec2.b:='b0';
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur0 IS SELECT 10 AS a, 'b0' AS b;
+BEGIN
+ FOR rec0 IN cur0
+ LOOP
+ DECLARE
+ CURSOR cur1 IS SELECT 11 AS a, 'b1' AS b;
+ BEGIN
+ rec0.a:= 11;
+ rec0.b:= 'b0';
+ FOR rec1 IN cur1
+ LOOP
+ rec1.a:= 11;
+ rec1.b:= 'b1';
+ DECLARE
+ CURSOR cur2 IS SELECT 12 AS a, 'b2' AS b;
+ BEGIN
+ FOR rec2 IN cur2
+ LOOP
+ rec2.a:=12;
+ rec2.b:='b2';
+ END LOOP;
+ END;
+ END LOOP;
+ END;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12098 sql_mode=ORACLE: Implicit cursor FOR loop
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ FOR rec1 IN (SELECT 11 AS a, 'b1' AS b)
+ LOOP
+ SELECT rec1.a, rec1.b;
+ rec1.a:= 11;
+ rec1.b:= 'b1';
+ SELECT rec1.a, rec1.b;
+ END LOOP;
+ FOR rec0 IN (SELECT 10 AS a, 'b0' AS b)
+ LOOP
+ rec0.a:= 10;
+ rec0.b:='b0';
+ END LOOP;
+ FOR rec2 IN (SELECT 12 AS a, 'b2' AS b)
+ LOOP
+ rec2.a:= 10;
+ rec2.b:='b0';
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ FOR rec0 IN (SELECT 10 AS a, 'b0' AS b)
+ LOOP
+ rec0.a:= 11;
+ rec0.b:= 'b0';
+ FOR rec1 IN (SELECT 11 AS a, 'b1' AS b)
+ LOOP
+ rec1.a:= 11;
+ rec1.b:= 'b1';
+ FOR rec2 IN (SELECT 12 AS a, 'b2' AS b)
+ LOOP
+ rec2.a:=12;
+ rec2.b:='b2';
+ END LOOP;
+ END LOOP;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations
+--echo #
+
+--echo #
+--echo # Cursor declaration and cursor%ROWTYPE declaration in the same block
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'a');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT a FROM t1;
+ rec1 cur1%ROWTYPE;
+BEGIN
+ rec1.a:= 10;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Recursive cursor and cursor%ROWTYPE declarations in the same block
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a INT:=10;
+ CURSOR cur1 IS SELECT a;
+ rec1 cur1%ROWTYPE;
+ CURSOR cur2 IS SELECT rec1.a + 1 "a";
+ rec2 cur2%ROWTYPE;
+BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SELECT rec1.a;
+ open cur2;
+ FETCH cur2 INTO rec2;
+ CLOSE cur2;
+ SELECT rec2.a;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12441 Variables declared after cursors with parameters lose values
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 INT:=101;
+BEGIN
+ OPEN cur(10,11);
+ CLOSE cur;
+ SELECT x0, x1;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur0(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 INT:=101;
+ CURSOR cur1(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x2 INT:=102;
+ CURSOR cur2(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x3 INT:=103;
+BEGIN
+ OPEN cur0(0,1);
+ CLOSE cur0;
+ SELECT x0, x1, x2, x3;
+ OPEN cur1(10,11);
+ CLOSE cur1;
+ SELECT x0, x1, x2, x3;
+ OPEN cur2(20,21);
+ CLOSE cur2;
+ SELECT x0, x1, x2, x3;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1();
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 t1.a%TYPE:=101;
+BEGIN
+ OPEN cur(10,11);
+ CLOSE cur;
+ SELECT x0, x1;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 ROW(a INT,b INT):=ROW(101,102);
+BEGIN
+ OPEN cur(10,11);
+ CLOSE cur;
+ SELECT x0, x1.a, x1.b;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1();
+DROP PROCEDURE p1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-cursor-decl.test b/mysql-test/suite/compat/oracle/t/sp-cursor-decl.test
new file mode 100644
index 00000000000..21683dd4220
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-cursor-decl.test
@@ -0,0 +1,295 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations
+--echo #
+
+--echo #
+--echo # Variable after cursor declaration
+--echo #
+
+CREATE TABLE t1 (a INT);
+insert into t1 values (1);
+insert into t1 values (2);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT a FROM t1;
+ var1 varchar(10);
+BEGIN
+ OPEN c;
+ fetch c into var1;
+ SELECT c%ROWCOUNT,var1;
+ close c;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+drop table t1;
+
+--echo #
+--echo # Variable after condition declaration
+--echo #
+
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ dup_key CONDITION FOR SQLSTATE '23000';
+ var1 varchar(40);
+ CONTINUE HANDLER FOR dup_key
+ BEGIN
+ var1:='duplicate key in index';
+ END;
+BEGIN
+ var1:='';
+ insert into t1 values (1);
+ select var1;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+drop table t1;
+
+--echo #
+--echo # Condition after cursor declaration
+--echo #
+
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ var1 varchar(40);
+ var2 integer;
+ CURSOR c IS SELECT col1 FROM t1;
+ dup_key CONDITION FOR SQLSTATE '23000';
+ CONTINUE HANDLER FOR dup_key
+ BEGIN
+ var1:='duplicate key in index';
+ END;
+BEGIN
+ var1:='';
+ insert into t1 values (1);
+ SELECT var1;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+drop table t1;
+
+--echo #
+--echo # Cursor after handler declaration
+--echo #
+
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1
+AS
+ var1 varchar(40);
+ var2 integer;
+ dup_key CONDITION FOR SQLSTATE '23000';
+ CONTINUE HANDLER FOR dup_key
+ BEGIN
+ var1:='duplicate key in index';
+ END;
+ CURSOR c IS SELECT col1 FROM t1;
+BEGIN
+ var1:='';
+ insert into t1 values (1);
+ SELECT var1;
+END;
+$$
+DELIMITER ;$$
+drop table t1;
+
+--echo #
+--echo # Condition after handler declaration
+--echo #
+
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1
+AS
+ var1 varchar(40);
+ var2 integer;
+ dup_key CONDITION FOR SQLSTATE '23000';
+ CURSOR c IS SELECT col1 FROM t1;
+ CONTINUE HANDLER FOR dup_key
+ BEGIN
+ var1:='duplicate key in index';
+ END;
+ divide_by_zero CONDITION FOR SQLSTATE '22012';
+BEGIN
+ var1:='';
+ insert into t1 values (1);
+ SELECT var1;
+END;
+$$
+DELIMITER ;$$
+drop table t1;
+
+--echo #
+--echo # Variable after handler declaration
+--echo #
+
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+create unique index t1_col1 on t1 (col1);
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1
+AS
+ var1 varchar(40);
+ var2 integer;
+ dup_key CONDITION FOR SQLSTATE '23000';
+ CURSOR c IS SELECT col1 FROM t1;
+ CONTINUE HANDLER FOR dup_key
+ BEGIN
+ var1:='duplicate key in index';
+ END;
+ divide_by_zero CONDITION FOR SQLSTATE '22012';
+BEGIN
+ var1:='';
+ insert into t1 values (1);
+ SELECT var1;
+END;
+$$
+DELIMITER ;$$
+drop table t1;
+
+--echo #
+--echo # Variable after cursor (inner block)
+--echo #
+
+CREATE TABLE t1 (col1 INT);
+insert into t1 values (1);
+insert into t1 values (2);
+create unique index t1_col1 on t1 (col1);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT col1 FROM t1;
+ var1 varchar(40);
+BEGIN
+ OPEN c;
+ begin
+ declare
+ CURSOR c IS SELECT col1 FROM t1 where col1=2;
+ var2 integer;
+ dup_key CONDITION FOR SQLSTATE '23000';
+ CONTINUE HANDLER FOR dup_key
+ BEGIN
+ var1:='duplicate key in index';
+ END;
+ begin
+ OPEN c;
+ fetch c into var1;
+ SELECT 'inner cursor',var1;
+ insert into t1 values (2);
+ close c;
+ end;
+ end;
+ SELECT var1;
+ fetch c into var1;
+ SELECT c%ROWCOUNT,var1;
+ begin
+ insert into t1 values (2);
+ exception when 1062 then
+ begin
+ SELECT 'dup key caugth';
+ end;
+ end;
+ close c;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+drop table t1;
+
+--echo #
+--echo # Cursor declaration and row type declaration in same block
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+insert into t1 values(1,'a');
+delimiter $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT a FROM t1;
+ rec1 cur1%ROWTYPE;
+BEGIN
+ rec1.a:= 10;
+END;
+$$
+delimiter ;$$
+call p1;
+DROP PROCEDURE p1;
+drop table t1;
+
+
+--echo #
+--echo # Recursive cursor and cursor%ROWTYPE declarations in the same block
+--echo #
+
+delimiter $$;
+CREATE PROCEDURE p1
+AS
+ a INT:=10;
+ b VARCHAR(10):='b0';
+ c DOUBLE:=0.1;
+ CURSOR cur1 IS SELECT a, b, c;
+ rec1 cur1%ROWTYPE;
+ CURSOR cur2 IS SELECT rec1.a + 1 "a", rec1.b||'0' AS b, rec1.c AS c;
+ rec2 cur2%ROWTYPE;
+BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SELECT rec1.a;
+ OPEN cur2;
+ FETCH cur2 INTO rec2;
+ CLOSE cur2;
+ SELECT rec2.a;
+ CREATE TABLE t2 AS SELECT rec2.a AS a, rec2.b AS b, rec2.c AS c;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12916 Wrong column data type for an INT field of a cursor-anchored ROW variable
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a INT DEFAULT 10;
+ CURSOR cur1 IS SELECT a;
+ rec1 cur1%ROWTYPE;
+BEGIN
+ CREATE TABLE t1 AS SELECT rec1.a;
+ SHOW CREATE TABLE t1;
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test b/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test
new file mode 100644
index 00000000000..3c37a732d8c
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test
@@ -0,0 +1,1424 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-12011 sql_mode=ORACLE: cursor%ROWTYPE in variable declarations
+--echo #
+
+--echo #
+--echo # A complete working example
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR c IS SELECT a,b FROM t1;
+BEGIN
+ DECLARE
+ rec c%ROWTYPE;
+ BEGIN
+ OPEN c;
+ LOOP
+ FETCH c INTO rec;
+ EXIT WHEN c%NOTFOUND;
+ SELECT 'rec=(' || rec.a ||','|| rec.b||')' AS c FROM dual;
+ INSERT INTO t2 VALUES (rec.a, rec.b);
+ END LOOP;
+ CLOSE c;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # cursor%ROWTYPE referring to a table in a non-existing database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM tes2.t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ NULL;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor%ROWTYPE referring to a table in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor%ROWTYPE referring to a table in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM test.t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Cursor%ROWTYPE referring to a view in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM v1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor%ROWTYPE referring to a view in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM test.v1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Checking that all cursor%ROWTYPE fields are NULL by default
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ BEGIN
+ SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A cursor%ROWTYPE variable with a ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE := ROW(10,'bbb');
+ BEGIN
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A cursor%ROWTYPE variable with an incompatible ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE := ROW(10,'bbb','ccc');
+ BEGIN
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A cursor%ROWTYPE variable with a ROW variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 ROW(a INT, b VARCHAR(10)):= ROW(10,'bbb');
+ rec2 cur%ROWTYPE := rec1;
+ BEGIN
+ SELECT rec2.a, rec2.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A ROW variable using a cursor%ROWTYPE variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE := ROW(10,'bbb');
+ rec2 ROW(a INT, b VARCHAR(10)):= rec1;
+ BEGIN
+ SELECT rec2.a, rec2.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning cursor%ROWTYPE variables with a different column count
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ rec2:=rec1;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ rec1:=rec2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning compatible cursor%ROWTYPE variables (equal number of fields)
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ rec1.a:= 10;
+ rec1.b:= 'bbb';
+ rec2:=rec1;
+ SELECT rec2.x, rec2.y;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between incompatible cursor%ROWTYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ rec2 ROW(x INT,y INT,z INT);
+ BEGIN
+ rec2.x:= 10;
+ rec2.y:= 20;
+ rec2.z:= 30;
+ rec1:= rec2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between compatible cursor%ROWTYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ rec2 ROW(x INT,y INT);
+ BEGIN
+ rec2.x:= 10;
+ rec2.y:= 20;
+ rec1:= rec2;
+ SELECT rec1.a, rec1.b;
+ rec1.a:= 11;
+ rec1.b:= 21;
+ rec2:= rec1;
+ SELECT rec2.x, rec2.y;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning cursor%ROWTYPE from a ROW expression
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ BEGIN
+ rec1:= ROW(10,20);
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor%ROWTYPE variable with a wrong field count
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+ DECLARE
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ CLOSE cur1;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_WRONG_NO_OF_FETCH_ARGS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor%ROWTYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ OPEN cur;
+ LOOP
+ FETCH cur INTO rec;
+ EXIT WHEN cur%NOTFOUND;
+ SELECT rec.a, rec.b, rec.c, rec.d;
+ INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+ END LOOP;
+ CLOSE cur;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor%ROWTYPE variable, cur%ROWTYPE declared inside the LOOP
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ OPEN cur;
+ LOOP
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ FETCH cur INTO rec;
+ EXIT WHEN cur%NOTFOUND;
+ SELECT rec.a, rec.b, rec.c, rec.d;
+ INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+ END;
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor%ROWTYPE variable with different column names
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+ DECLARE
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.x, rec2.y;
+ CLOSE cur1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor%ROWTYPE variable, with truncation
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ CURSOR cur2 IS SELECT * FROM t2;
+BEGIN
+ DECLARE
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.a, rec2.b;
+ CLOSE cur1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor%ROWTYPE variables are not allowed in LIMIT
+--echo #
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE:=(1,2);
+ BEGIN
+ SELECT * FROM t1 LIMIT rec1.a;
+ END;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # cursor%ROWTYPE variable fields as OUT parameters
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT INT,b OUT VARCHAR(10))
+AS
+BEGIN
+ a:=10;
+ b:='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ BEGIN
+ CALL p1(rec1.a, rec1.b);
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire cursor%ROWTYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur%ROWTYPE:= ROW(10,'bb');
+ BEGIN
+ CALL p1(rec1);
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire cursor%ROWTYPE variable as an OUT parameter
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+ a:= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur%ROWTYPE;
+ BEGIN
+ CALL p1(rec1);
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Assigning a cursor%ROWTYPE field to an OUT parameter
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1 (res IN OUT INTEGER)
+AS
+ a INT:=10;
+ CURSOR cur1 IS SELECT a FROM DUAL;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ res:=rec1.a;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1(@res);
+SELECT @res;
+SET @res=NULL;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing Item_splocal_row_field_by_name::print
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur1%ROWTYPE:=ROW(10,'bb');
+ BEGIN
+ EXPLAIN EXTENDED SELECT rec.a, rec.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Run time error in the cursor statement
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur1 IS SELECT
+ 10 AS a,
+ CONCAT(_latin1'a' COLLATE latin1_bin,
+ _latin1'a' COLLATE latin1_swedish_ci) AS b;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SELECT a,b;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_CANT_AGGREGATE_2COLLATIONS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+
+--echo #
+--echo # Non-existing field
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur1%ROWTYPE;
+ BEGIN
+ SELECT rec.c;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+ALTER TABLE t1 ADD c INT;
+#
+# The below ALTER is needed as a workaround to call sp_cache_invalidate()
+# Please remove it after fixing MDEV-12166
+#
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that field names are case insensitive
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE:=ROW(10,'bb');
+ BEGIN
+ SELECT rec.A, rec.B;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that cursor%ROWTYPE uses temporary tables vs shadowed real tables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE:=ROW(10,'bb');
+ BEGIN
+ SELECT rec.A, rec.B;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TEMPORARY TABLE t1;
+#
+# The below ALTER is needed as a workaround to call sp_cache_invalidate()
+# Please remove it after fixing MDEV-12166
+#
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that the structure of cursor%ROWTYPE variables is determined at the CURSOR instantiation time
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DROP TABLE t1;
+ CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+ DECLARE
+ rec cur%ROWTYPE; -- This has a column "c"
+ BEGIN
+ rec.c:=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE; -- This does not have a column "c"
+ BEGIN
+ DROP TABLE t1;
+ CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+ rec.c:=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Duplicate field nams in a cursor referenced by %ROWTYPE
+--echo #
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur IS SELECT * FROM t1, t2;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ SELECT rec.a;
+ rec.a:=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_DUP_FIELDNAME
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Tricky field names a cursor referenced by %ROWTYPE
+--echo #
+
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('a');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur IS SELECT a, CONCAT(a,'a'), CONCAT(a,'ö') FROM t1;
+BEGIN
+ DECLARE
+ rec cur%ROWTYPE;
+ BEGIN
+ OPEN cur;
+ FETCH cur INTO rec;
+ CLOSE cur;
+ SELECT rec.a, rec."CONCAT(a,'a')", rec."CONCAT(a,'ö')";
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SET NAMES latin1;
+
+
+--echo #
+--echo # Using definitions recursively (cursor%ROWTYPE variables in another cursor SELECT)
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b1'),(20,'b2'),(30,'b3');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur1 IS SELECT a,b FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE:=ROW(0,'b0');
+ CURSOR cur2 IS SELECT rec1.a AS a, rec1.b AS b FROM t1;
+ BEGIN
+ DECLARE
+ rec2 cur2%ROWTYPE;
+ BEGIN
+ OPEN cur2;
+ LOOP
+ FETCH cur2 INTO rec2;
+ EXIT WHEN cur2%NOTFOUND;
+ SELECT rec2.a, rec2.b;
+ END LOOP;
+ CLOSE cur2;
+ END;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing queries with auto-generated Items.
+--echo # An instance of Item_func_conv_charset is created during the below SELECT query.
+--echo # We check here that during an implicit cursor OPEN
+--echo # done in sp_instr_cursor_copy_struct::exec_core()
+--echo # all temporary Items are created on a proper memory root and are safely destroyed.
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b VARCHAR(10) CHARACTER SET utf8);
+INSERT INTO t1 VALUES (0xFF, 'a');
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur1 IS SELECT CONCAT(a,b) AS c FROM t1;
+BEGIN
+ DECLARE
+ rec1 cur1%ROWTYPE;
+ BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SELECT HEX(rec1.c);
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-10581 sql_mode=ORACLE: Explicit cursor FOR LOOP
+--echo #
+
+--echo # IN followed by a non-identifier
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 AS
+ CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+ FOR rec IN 10
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # IN followed by a quoted identifier: table.column
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 AS
+ CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+ FOR rec IN c1.c2
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # IN followed by a quoted identifier: .table.column
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 AS
+ CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+ FOR rec IN .c1.c2
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # IN followed by a quoted identifier: schema.table.column
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 AS
+ CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+ FOR rec IN c1.c2.c3
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # IN followed by an unknown cursor name
+
+DELIMITER $$;
+--error ER_SP_CURSOR_MISMATCH
+CREATE PROCEDURE p1 AS
+ CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+ FOR rec IN c2
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # Make sure "rec" shadows other declarations outside the loop
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10, 'b0');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec INT:=10;
+ CURSOR c1 IS SELECT a,b FROM t1;
+BEGIN
+ FOR rec IN c1
+ LOOP
+ SELECT rec.a;
+ END LOOP;
+ SELECT rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo # Make sure "rec" is not visible after END LOOP
+
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1 AS
+ CURSOR c1 IS SELECT 'test' AS a FROM DUAL;
+BEGIN
+ FOR rec IN c1
+ LOOP
+ NULL;
+ END LOOP;
+ rec.a:= 10;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # Make sure that duplicate column names are not allowed
+
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur IS SELECT 'a' AS a, 'A' as a;
+BEGIN
+ FOR rec IN cur
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+--error ER_DUP_FIELDNAME
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo # A complete working example
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b0');
+INSERT INTO t1 VALUES (11,'b1');
+INSERT INTO t1 VALUES (12,'b2');
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur IS SELECT a, b FROM t1;
+BEGIN
+ FOR rec IN cur
+ LOOP
+ SELECT rec.a, rec.b;
+ INSERT INTO t2 VALUES (rec.a, rec.b);
+ rec.a:= rec.a + 1000;
+ rec.b:= 'b' || rec.b;
+ INSERT INTO t3 VALUES (rec.a, rec.b);
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+SELECT * FROM t3;
+DROP PROCEDURE p1;
+DROP TABLE t3;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12314 Implicit cursor FOR LOOP for cursors with parameters
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b0');
+INSERT INTO t1 VALUES (11,'b1');
+INSERT INTO t1 VALUES (12,'b2');
+DELIMITER $$;
+CREATE PROCEDURE p1(pa INT, pb VARCHAR(32)) AS
+ CURSOR cur(va INT, vb VARCHAR(32)) IS
+ SELECT a, b FROM t1 WHERE a=va AND b=vb;
+BEGIN
+ FOR rec IN cur(pa,pb)
+ LOOP
+ SELECT rec.a, rec.b;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1(10,'B0');
+CALL p1(11,'B1');
+CALL p1(12,'B2');
+CALL p1(12,'non-existing');
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12098 sql_mode=ORACLE: Implicit cursor FOR loop
+--echo #
+
+--echo # Parse error in the cursor SELECT statement
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT a, b FROM)
+ LOOP
+ SELECT rec.a, rec.b;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo # Make sure "rec" is not visible after END LOOP
+
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT 'test' AS a)
+ LOOP
+ NULL;
+ END LOOP;
+ rec.a:= 10;
+END;
+$$
+DELIMITER ;$$
+
+--echo # Make sure "rec" is not visible inside the SELECT statement
+
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT rec)
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT rec.a)
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+--error ER_UNKNOWN_TABLE
+CALL p1;
+DROP PROCEDURE p1;
+
+--echo # Totally confusing name mixture
+
+CREATE TABLE rec (rec INT);
+INSERT INTO rec VALUES (10);
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT rec FROM rec)
+ LOOP
+ SELECT rec.rec;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE rec;
+
+
+--echo # Make sure that duplicate column names are not allowed
+
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT 'a' AS a, 'A' as a)
+ LOOP
+ NULL;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+--error ER_DUP_FIELDNAME
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo # A complete working example
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b0');
+INSERT INTO t1 VALUES (11,'b1');
+INSERT INTO t1 VALUES (12,'b2');
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec IN (SELECT a, b FROM t1)
+ LOOP
+ SELECT rec.a, rec.b;
+ INSERT INTO t2 VALUES (rec.a, rec.b);
+ rec.a:= rec.a + 1000;
+ rec.b:= 'b'|| rec.b;
+ INSERT INTO t3 VALUES (rec.a, rec.b);
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+SELECT * FROM t3;
+DROP PROCEDURE p1;
+DROP TABLE t3;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo # A combination of explicit and implicit cursors
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b1');
+INSERT INTO t1 VALUES (11,'b2');
+INSERT INTO t1 VALUES (12,'b3');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ FOR rec1 IN (SELECT a, b FROM t1)
+ LOOP
+ DECLARE
+ CURSOR cur2 IS SELECT a+1000 AS a, 'bb'||b AS b FROM t1 WHERE a=rec1.a AND b=rec1.b;
+ BEGIN
+ SELECT rec1.a, rec1.b;
+ FOR rec2 IN cur2
+ LOOP
+ SELECT rec2.a, rec2.b;
+ END LOOP;
+ END;
+ END LOOP;
+ FOR rec1 IN (SELECT a,b FROM t1)
+ LOOP
+ FOR rec2 IN (SELECT a+2000 AS a,'bbb'||b AS b FROM t1 WHERE a=rec1.a AND b=rec1.b)
+ LOOP
+ SELECT rec2.a, rec2.b;
+ END LOOP;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-cursor.test b/mysql-test/suite/compat/oracle/t/sp-cursor.test
new file mode 100644
index 00000000000..5a8b7b69f67
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-cursor.test
@@ -0,0 +1,954 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
+--echo #
+
+
+--echo #
+--echo # Cursor attributes outside of an SP context
+--echo #
+
+--error ER_SP_CURSOR_MISMATCH
+SELECT c%ISOPEN;
+--error ER_SP_CURSOR_MISMATCH
+SELECT c%FOUND;
+--error ER_SP_CURSOR_MISMATCH
+SELECT c%NOTFOUND;
+--error ER_SP_CURSOR_MISMATCH
+SELECT c%ROWCOUNT;
+
+
+--echo #
+--echo # Undefinite cursor attributes
+--echo #
+
+DELIMITER $$;
+--error ER_SP_CURSOR_MISMATCH
+CREATE PROCEDURE p1
+AS
+BEGIN
+ SELECT c%ISOPEN;
+END;
+$$
+--error ER_SP_CURSOR_MISMATCH
+CREATE PROCEDURE p1
+AS
+BEGIN
+ SELECT c%ROWCOUNT;
+END;
+$$
+--error ER_SP_CURSOR_MISMATCH
+CREATE PROCEDURE p1
+AS
+BEGIN
+ SELECT c%FOUND;
+END;
+$$
+--error ER_SP_CURSOR_MISMATCH
+CREATE PROCEDURE p1
+AS
+BEGIN
+ SELECT c%NOTFOUND;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ SELECT c%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_CURSOR_NOT_OPEN
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ SELECT c%FOUND;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_CURSOR_NOT_OPEN
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ SELECT c%NOTFOUND;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_CURSOR_NOT_OPEN
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Not opened cursor attributes %FOUND, %NOTFOUND, %ROWCOUNT with INVALID_CURSOR exception
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ SELECT c%ROWCOUNT;
+EXCEPTION
+ WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ SELECT c%FOUND;
+EXCEPTION
+ WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ SELECT c%NOTFOUND;
+EXCEPTION
+ WHEN INVALID_CURSOR THEN SELECT 'INVALID_CURSOR caught' AS msg;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # print()
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+ EXPLAIN EXTENDED SELECT c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Declared data type of the attributes
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+ OPEN c;
+ CREATE TABLE t2 AS SELECT c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Core functionality
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (30);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a INT:=0;
+ CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+ SELECT a, c%ISOPEN;
+ OPEN c;
+ /*
+ After OPEN and before FETCH:
+ - %ROWCOUNT returns 0
+ - %FOUND and %NOTFOUND return NULL
+ */
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ FETCH c INTO a;
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ FETCH c INTO a;
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ FETCH c INTO a;
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ FETCH c INTO a;
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ CLOSE c;
+ SELECT a, c%ISOPEN;
+ /*
+ After reopen and before FETCH:
+ - %ROWCOUNT returns 0
+ - %FOUND and %NOTFOUND return NULL
+ */
+ OPEN c;
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ FETCH c INTO a;
+ SELECT a, c%ISOPEN, c%ROWCOUNT, c%FOUND, c%NOTFOUND;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %NOTFOUND as a loop exit condition
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (30);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a INT:=0;
+ CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+ OPEN c;
+ LOOP
+ FETCH c INTO a;
+ EXIT WHEN c%NOTFOUND;
+ SELECT a;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %FOUND as a loop exit condition
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+INSERT INTO t1 VALUES (30);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a INT:=0;
+ CURSOR c IS SELECT * FROM t1 ORDER BY a;
+BEGIN
+ OPEN c;
+ LOOP
+ FETCH c INTO a;
+ EXIT WHEN NOT c%FOUND;
+ SELECT a;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of MDEV-10582 sql_mode=ORACLE: explicit cursor attributes %ISOPEN, %ROWCOUNT, %FOUND, %NOTFOUND
+--echo #
+
+--echo #
+--echo # MDEV-10597 Cursors with parameters
+--echo #
+
+--echo #
+--echo # OPEN with a wrong number of parameters
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+--error ER_WRONG_PARAMCOUNT_TO_CURSOR
+CREATE PROCEDURE p1(a_a INT,a_b VARCHAR)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
+BEGIN
+ OPEN c(a_a);
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ DBMS_OUTPUT.PUT_LINE('Fetched a record a='||TO_CHAR(v_a)||' b='||v_b);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # Cursor parameters are not visible outside of the cursor
+--echo #
+
+DELIMITER $$;
+--error ER_UNKNOWN_SYSTEM_VARIABLE
+CREATE PROCEDURE p1(a_a INT)
+AS
+ v_a INT;
+ CURSOR c (p_a INT) IS SELECT a FROM t1 WHERE a=p_a;
+BEGIN
+ OPEN c(a_a);
+ p_a:=10;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_UNKNOWN_SYSTEM_VARIABLE
+CREATE PROCEDURE p1(a_a INT)
+AS
+ v_a INT;
+ CURSOR c (p_a INT) IS SELECT a FROM t1 WHERE a=p_a;
+BEGIN
+ p_a:=10;
+ OPEN c(a_a);
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Cursor parameter shadowing a local variable
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT)
+AS
+ v_a INT:=NULL;
+ p_a INT:=NULL;
+ CURSOR c (p_a VARCHAR2) IS SELECT a FROM t1 WHERE p_a IS NOT NULL;
+BEGIN
+ OPEN c(a);
+ FETCH c INTO v_a;
+ IF c%NOTFOUND THEN
+ BEGIN
+ SELECT 'No records found' AS msg;
+ RETURN;
+ END;
+ END IF;
+ CLOSE c;
+ SELECT 'Fetched a record a='||v_a AS msg;
+ INSERT INTO t1 VALUES (v_a);
+END;
+$$
+DELIMITER ;$$
+CALL p1(1);
+SELECT * FROM t1;
+CALL p1(NULL);
+SELECT * FROM t1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Parameters in SELECT list
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR c (p_a INT, p_b VARCHAR) IS SELECT p_a,p_b FROM DUAL;
+BEGIN
+ FOR i IN 0..1
+ LOOP
+ OPEN c(a_a + i,a_b);
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT 'Fetched a record a=' || v_a || ' b=' || v_b AS msg;
+ END LOOP;
+ CLOSE c;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1,'b1');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Parameters in SELECT list + UNION
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR c (p_a INT, p_b VARCHAR) IS
+ SELECT p_a,p_b FROM DUAL
+ UNION ALL
+ SELECT p_a+1,p_b||'b' FROM DUAL;
+BEGIN
+ OPEN c(a_a,a_b);
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT 'Fetched a record a=' || v_a || ' b=' || v_b AS msg;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1,'b1');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Parameters in SELECT list + type conversion + warnings
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a VARCHAR)
+AS
+ v_a INT;
+ CURSOR c (p_a INT) IS SELECT p_a FROM DUAL;
+BEGIN
+ OPEN c(a_a);
+ LOOP
+ FETCH c INTO v_a;
+ EXIT WHEN c%NOTFOUND;
+ SELECT 'Fetched a record a=' || v_a AS msg;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('1b');
+CALL p1('b1');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # One parameter in SELECT list + subselect
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a VARCHAR)
+AS
+ v_a VARCHAR(10);
+ CURSOR c (p_a VARCHAR) IS
+ SELECT p_a FROM DUAL UNION SELECT REVERSE(p_a) FROM DUAL;
+BEGIN
+ OPEN c((SELECT a_a));
+ LOOP
+ FETCH c INTO v_a;
+ EXIT WHEN c%NOTFOUND;
+ SELECT v_a;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('ab');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Two parameters in SELECT list + subselect
+--echo #
+
+SET sql_mode=ORACLE;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ v_a VARCHAR(10);
+ v_b VARCHAR(20);
+ CURSOR c (p_a VARCHAR, p_b VARCHAR) IS
+ SELECT p_a, p_b FROM DUAL
+ UNION
+ SELECT p_b, p_a FROM DUAL;
+BEGIN
+ OPEN c((SELECT 'aaa'),(SELECT 'bbb'));
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT v_a, v_b;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Two parameters in SELECT list + two parameters in WHERE + subselects
+--echo #
+
+SET sql_mode=ORACLE;
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a VARCHAR, a_b VARCHAR)
+AS
+ v_a VARCHAR(10);
+ v_b VARCHAR(20);
+ CURSOR c (value_a VARCHAR, value_b VARCHAR,
+ pattern_a VARCHAR, pattern_b VARCHAR) IS
+ SELECT value_a, value_b FROM DUAL WHERE value_a LIKE pattern_a
+ UNION
+ SELECT value_b, value_a FROM DUAL WHERE value_b LIKE pattern_b;
+BEGIN
+ OPEN c((SELECT 'aaa'),(SELECT 'bbb'),(SELECT a_a),(SELECT a_b));
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT v_a, v_b;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('%','%');
+CALL p1('aaa','xxx');
+CALL p1('xxx','bbb');
+CALL p1('xxx','xxx');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Parameters in SELECT list + stored function
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1 (a VARCHAR) RETURN VARCHAR
+AS
+BEGIN
+ RETURN a || 'y';
+END;
+$$
+CREATE PROCEDURE p1(a_a VARCHAR)
+AS
+ v_a VARCHAR(10);
+ v_b VARCHAR(10);
+ CURSOR c (p_sel_a VARCHAR, p_cmp_a VARCHAR) IS
+ SELECT p_sel_a, p_cmp_a FROM DUAL;
+BEGIN
+ OPEN c(f1(a_a), f1(a_a));
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT v_a;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('x');
+# A complex expression
+CALL p1(f1(COALESCE(NULL, f1('x'))));
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # One parameter in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR c (p_a INT) IS SELECT a,b FROM t1 WHERE a=p_a;
+BEGIN
+ OPEN c(a_a);
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ INSERT INTO t2 VALUES (v_a,v_b);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1);
+SELECT * FROM t2;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Two parameters in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR c (p_a INT, p_b VARCHAR) IS SELECT a,b FROM t1 WHERE a=p_a AND b=p_b;
+BEGIN
+ OPEN c(a_a, a_b);
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ INSERT INTO t2 VALUES (v_a,v_b);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1,'11');
+SELECT * FROM t2;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Parameters in WHERE and HAVING clauses
+--echo #
+CREATE TABLE t1 (name VARCHAR(10), value INT);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bot',1);
+DELIMITER $$;
+CREATE PROCEDURE p1 (arg_name_limit VARCHAR, arg_total_limit INT)
+AS
+ v_name VARCHAR(10);
+ v_total INT;
+-- +0 is needed to work around the bug MDEV-11081
+ CURSOR c(p_v INT) IS
+ SELECT name, SUM(value + p_v) + 0 AS total FROM t1
+ WHERE name LIKE arg_name_limit
+ GROUP BY name HAVING total>=arg_total_limit;
+BEGIN
+ FOR i IN 0..1
+ LOOP
+ OPEN c(i);
+ LOOP
+ FETCH c INTO v_name, v_total;
+ EXIT WHEN c%NOTFOUND;
+ SELECT v_name, v_total;
+ END LOOP;
+ CLOSE c;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+CALL p1('%', 2);
+CALL p1('b_t', 0);
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # One parameter in LIMIT clause
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'b1');
+INSERT INTO t1 VALUES (2,'b2');
+INSERT INTO t1 VALUES (3,'b3');
+INSERT INTO t1 VALUES (4,'b4');
+INSERT INTO t1 VALUES (5,'b5');
+INSERT INTO t1 VALUES (6,'b6');
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR c (p_a INT) IS SELECT a,b FROM t1 ORDER BY a LIMIT p_a;
+BEGIN
+ CREATE TABLE t2 (a INT, b VARCHAR(10));
+ OPEN c(a_a);
+ LOOP
+ FETCH c INTO v_a, v_b;
+ EXIT WHEN c%NOTFOUND;
+ INSERT INTO t2 VALUES (v_a,v_b);
+ END LOOP;
+ CLOSE c;
+ SELECT * FROM t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1);
+CALL p1(3);
+CALL p1(6);
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # End of MDEV-10597 Cursors with parameters
+--echo #
+
+--echo #
+--echo # MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'A');
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1(a INT,b VARCHAR)
+AS
+ CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
+BEGIN
+ OPEN c(a+, b);
+ LOOP
+ FETCH c INTO a, b;
+ EXIT WHEN c%NOTFOUND;
+ SELECT a, b;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
+INSERT INTO t1 VALUES (1,'b1','2001-01-01 10:20:30.123');
+INSERT INTO t1 VALUES (2,'b2','2001-01-02 10:20:30.123');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ v_a t1.a%TYPE;
+ v_b t1.b%TYPE;
+ v_c t1.c%TYPE;
+ CURSOR c IS SELECT a,b,c FROM t1;
+BEGIN
+ OPEN c;
+ LOOP
+ FETCH c INTO v_a, v_b, v_c;
+ EXIT WHEN c%NOTFOUND;
+ INSERT INTO t2 (a,b,c) VALUES (v_a, v_b, v_c);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12007 Allow ROW variables as a cursor FETCH target
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec ROW(a INT, b VARCHAR(32));
+ CURSOR c IS SELECT a,b FROM t1;
+BEGIN
+ OPEN c;
+ LOOP
+ FETCH c INTO rec;
+ EXIT WHEN c%NOTFOUND;
+ SELECT ('rec=(' || rec.a ||','|| rec.b||')') AS c;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12441 Variables declared after cursors with parameters lose values
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 INT:=101;
+BEGIN
+ OPEN cur(10,11);
+ CLOSE cur;
+ SELECT x0, x1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 t1.a%TYPE:=101;
+BEGIN
+ OPEN cur(10,11);
+ CLOSE cur;
+ SELECT x0, x1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
+ x1 ROW(a INT,b INT):=ROW(101,102);
+BEGIN
+ OPEN cur(10,11);
+ CLOSE cur;
+ SELECT x0, x1.a, x1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'Tbl-t1.b0');
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT a,b FROM t1;
+ x1 t1%ROWTYPE:=ROW(101,'Var-x1.b0');
+BEGIN
+ SELECT x0, x1.a, x1.b;
+ OPEN cur(10,11);
+ FETCH cur INTO x1;
+ CLOSE cur;
+ SELECT x0, x1.a, x1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'Tbl-t1.b0');
+DELIMITER $$;
+CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(cp1 INT, cp2 INT) IS SELECT a,b FROM t1;
+ x1 cur%ROWTYPE:=ROW(101,'Var-x1.b0');
+BEGIN
+ SELECT x0, x1.a, x1.b;
+ OPEN cur(10,11);
+ FETCH cur INTO x1;
+ CLOSE cur;
+ SELECT x0, x1.a, x1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+DELIMITER $$;
+DECLARE
+ CURSOR c IS SELECT 1 AS c FROM DUAL;
+BEGIN
+ OPEN c;
+ SELECT
+ c%ISOPEN,
+ c%NOTFOUND,
+ c%FOUND,
+ c%ROWCOUNT;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/suite/compat/oracle/t/sp-goto.test b/mysql-test/suite/compat/oracle/t/sp-goto.test
new file mode 100644
index 00000000000..df7f1132666
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-goto.test
@@ -0,0 +1,872 @@
+set sql_mode=oracle;
+--echo #
+--echo # MDEV-10697 sql_mode=ORACLE: GOTO statement
+--echo #
+
+--echo # matrice of tests in procedure
+--echo # |--------------------------------------------------------
+--echo # | | Same | Outside | to sub | No |
+--echo # | | block | one block | block | matching |
+--echo # | | | | | label |
+--echo # |--------------------------------------------------------
+--echo # | Forward jump | F1 | F3 | F5 | F7 |
+--echo # |--------------------------------------------------------
+--echo # | Backward jump | F2 | F4 | F6 | F8 |
+--echo # |--------------------------------------------------------
+--echo # Jump from handler to outside handling code block : F9
+--echo # Jump from handler to handling code block : F10 (forbidden)
+--echo # Jump inside handler : F21
+--echo # Jump between handler : F22 (forbidden)
+--echo # Jump from cascaded block with handler : F11
+--echo # Duplicate label in same block : F12 (forbidden)
+--echo # Duplicate label in different block : F13
+--echo # Jump outside unlabeled block : F14
+--echo # Jump inside/outside labeled block : F15
+--echo # Jump from if / else : F16
+--echo # Jump with cursors : F17
+--echo # Jump outside case : F18
+--echo # Jump inside/outside case block : F19
+--echo # Jump outside labeled loop : F20
+--echo # Jump (continue) labeled loop : F23
+--echo # Two consecutive label : P24
+--echo # Two consecutive label (backward and forward jump) : P25
+--echo # Two consecutive label, continue to wrong label : P26
+--echo # Consecutive goto label and block label : P27
+
+--echo # Test in function
+--echo # backward jump : func1
+--echo # forward jump : func2
+
+--echo # Test in trigger
+--echo # forward jump : trg1
+
+--echo #
+--echo # Forward jump in same block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f1(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ p2:='a';
+ goto lab1;
+<<lab1>>
+ goto lab2;
+ p2:='b';
+<<lab2>>
+ return ;
+END;
+$$
+
+DELIMITER ;$$
+call f1(@wp1);
+select 'f1',@wp1;
+DROP PROCEDURE f1;
+
+--echo #
+--echo # Backward jump in same block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f2(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ p2:='a';
+<<lab1>>
+ if (p2='b') then
+ return ;
+ end if;
+ p2:='b';
+ goto lab1;
+END;
+$$
+DELIMITER ;$$
+call f2(@wp1);
+select 'f2',@wp1;
+DROP PROCEDURE f2;
+
+--echo #
+--echo # Forward jump outside one block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f3(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ p2:='a';
+ if (p2='a') then
+ goto lab1;
+ end if;
+ p2:='c';
+<<lab1>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+call f3(@wp1);
+select 'f3',@wp1;
+DROP PROCEDURE f3;
+
+--echo #
+--echo # Backward jump outside one block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f4(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ p2:='a';
+<<lab1>>
+ if (p2='a') then
+ p2:=p2||'b';
+ goto lab1;
+ end if;
+ if (p2='ab') then
+ p2:=p2||'c';
+ end if;
+ return ;
+END;
+$$
+DELIMITER ;$$
+call f4(@wp1);
+select 'f4',@wp1;
+DROP PROCEDURE f4;
+
+DELIMITER $$;
+--echo #
+--echo # Forward jump inside sub block
+--error ER_SP_LILABEL_MISMATCH
+CREATE or replace procedure f5(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ p2:='a';
+goto lab5 ;
+ if (p2='a') then
+<<lab5>>
+ p2:=p2||'b';
+ end if;
+ return ;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--echo #
+--echo # Backward jump inside sub block
+--error ER_SP_LILABEL_MISMATCH
+CREATE or replace procedure f6(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ p2:='a';
+ if (p2='a') then
+<<lab6>>
+ p2:=p2||'b';
+ return ;
+ end if;
+goto lab6 ;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--echo #
+--echo # Backward jump - missing label
+--error ER_SP_LILABEL_MISMATCH
+CREATE or replace procedure f7(p2 IN OUT VARCHAR)
+AS
+BEGIN
+<<lab>>
+ goto lab7 ;
+ return ;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--echo #
+--echo # Forward jump - missing label
+--error ER_SP_LILABEL_MISMATCH
+CREATE or replace procedure f8(p2 IN OUT VARCHAR)
+AS
+BEGIN
+ goto lab8 ;
+<<lab>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # Jump from handler to procedure code
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f9(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+<<lab9>>
+ if lim=-1 then
+ res:=res||' -- goto end limit -1 --';
+ goto lab9_end;
+ end if;
+
+ begin
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ begin
+ res:=res||'--- too_many_rows cought ---';
+ lim:=0;
+ goto lab9;
+ end;
+ WHEN NO_DATA_FOUND THEN
+ begin
+ res:=res||'--- no_data_found cought ---';
+ lim:=-1;
+ goto lab9;
+ end;
+ end;
+ res:=res||'error';
+<<lab9_end>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f9(2, @res);
+SELECT 'f9',@res;
+CALL f9(0, @res);
+SELECT 'f9',@res;
+DROP PROCEDURE f9;
+
+DELIMITER $$;
+--echo #
+--echo # Jump from handler to handling bloc
+--error ER_SP_LILABEL_MISMATCH
+CREATE or replace procedure f10(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ begin
+<<lab10>>
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ begin
+ res:='--- too_many_rows cought ---';
+ goto lab10;
+ end;
+ WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought ---';
+ end;
+ return ;
+END;
+$$
+
+--echo #
+--echo # Jump from cascaded block with handler
+--echo #
+CREATE or replace procedure f11(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+<<lab11a>>
+ begin
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ begin
+ res:=res||'--- too_many_rows cought 1 ---';
+ goto lab11b;
+ end;
+ WHEN NO_DATA_FOUND THEN
+ begin
+ res:=res||'--- no_data_found cought 1 ---';
+ lim:=2;
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ begin
+ res:=res||'--- too_many_rows cought 2 ---';
+ goto lab11a;
+ end;
+ WHEN NO_DATA_FOUND THEN res:='--- no_data_found cought 2 ---';
+ end;
+ end;
+ set res:=res||' error ';
+<<lab11b>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f11(0, @res);
+SELECT 'f11',@res;
+DROP PROCEDURE f11;
+
+DELIMITER $$;
+--echo #
+--echo # Jump inside handler
+--echo #
+CREATE or replace procedure f21(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ begin
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ begin
+ <<retry>>
+ lim:=lim-1;
+ loop
+ begin
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ begin
+ lim:=lim-1;
+ goto retry;
+ end;
+ end;
+ exit ;
+ end loop;
+ end;
+ end;
+ res:=lim;
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f21(10, @res);
+SELECT 'f21',@res;
+drop procedure f21;
+
+DELIMITER $$;
+--echo #
+--echo # Jump beetween handler
+--error ER_SP_LILABEL_MISMATCH
+CREATE or replace procedure f22(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ res:='ok';
+ begin
+ SELECT a INTO a FROM information_schema.tables LIMIT lim;
+ EXCEPTION
+ WHEN TOO_MANY_ROWS THEN
+ goto nodata ;
+ WHEN NO_DATA_FOUND THEN
+ begin
+<<nodata>>
+ res:='error';
+ end;
+ end;
+ return ;
+END;
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--echo #
+--echo # Duplicate label in same bloc
+--error 1309
+CREATE or replace procedure f12(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+<<lab12>>
+ res:='error';
+<<lab12>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # Duplicate label in different block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f13(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ a:=0;
+<<lab13>>
+ a:=a+1;
+ begin
+ <<lab13>>
+ a:=a+1;
+ if (a<10) then
+ goto lab13;
+ end if;
+ end;
+ res:=a;
+ if (a=10) then
+ goto lab13;
+ end if;
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f13(0, @res);
+SELECT 'f13',@res;
+DROP PROCEDURE f13;
+
+
+--echo #
+--echo # Jump outside unlabeled block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f14(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ a:=0;
+ loop
+ a:=a+1;
+ if (a<10) then
+ continue;
+ end if;
+ if (a>=lim) then
+ goto lab14;
+ end if;
+ if (a>=20) then
+ exit;
+ end if;
+ end loop;
+<<lab14>>
+ res:=a;
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f14(15, @res);
+SELECT 'f14',@res;
+CALL f14(8, @res);
+SELECT 'f14',@res;
+CALL f14(25, @res);
+SELECT 'f14',@res;
+DROP PROCEDURE f14;
+
+--echo #
+--echo # Jump inside/outside labeled block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f15(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ a:=0;
+ <<looplabel>> loop
+ <<beginlooplabel>>
+ a:=a+1;
+ if (a<10) then
+ continue looplabel;
+ end if;
+ if (a>=lim) then
+ goto lab15;
+ end if;
+ if (a>=20) then
+ exit looplabel;
+ end if;
+ goto beginlooplabel;
+ end loop;
+<<lab15>>
+ res:=a;
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f15(15, @res);
+SELECT 'f15',@res;
+CALL f15(8, @res);
+SELECT 'f15',@res;
+CALL f15(25, @res);
+SELECT 'f15',@res;
+DROP PROCEDURE f15;
+
+--echo #
+--echo # Jump from if / else
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f16(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ if (lim<10) then
+ goto lab16_1;
+ else
+ goto lab16_2;
+ end if;
+<<lab16_1>>
+ res:='if lab16_1';
+ goto lab16_3;
+<<lab16_2>>
+ res:='else lab16_2';
+ goto lab16_3;
+ res:='error lab16_3';
+<<lab16_3>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f16(15, @res);
+SELECT 'f16',@res;
+CALL f16(8, @res);
+SELECT 'f16',@res;
+DROP PROCEDURE f16;
+
+--echo #
+--echo # Jump with cursors
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f17(lim INT, res OUT VARCHAR)
+AS
+ v_a INT;
+ v_b VARCHAR(10);
+ CURSOR cur1 IS SELECT 1 FROM dual where 1=2;
+BEGIN
+ OPEN cur1;
+ LOOP
+ FETCH cur1 INTO v_a;
+ EXIT WHEN cur1%NOTFOUND;
+ END LOOP;
+ CLOSE cur1;
+ <<lab17>>
+ lim:=lim-1;
+ begin
+ declare
+ CURSOR cur1 IS SELECT 1 FROM dual;
+ CURSOR cur2 IS SELECT 1 FROM dual where 1=2;
+ begin
+ LOOP
+ OPEN cur1;
+ FETCH cur1 INTO v_a;
+ EXIT WHEN cur1%NOTFOUND;
+ res:=res||'-'||lim ;
+ close cur1;
+ if (lim>0) then
+ goto lab17;
+ else
+ goto lab17_end;
+ end if;
+ END LOOP;
+ end;
+ <<lab17_end>>
+ null;
+ end;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f17(5, @res);
+SELECT 'f17',@res;
+DROP PROCEDURE f17;
+
+--echo #
+--echo # Jump outside case
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f18(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ case lim
+ when 1 then
+ res:='case branch 18_1';
+ goto lab18_1;
+ res:='error';
+ when 2 then
+ res:='case branch 18_2';
+ goto lab18_2;
+ res:='error';
+ else
+ res:='default branch 18';
+ end case;
+<<lab18_1>>
+ null;
+<<lab18_2>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f18(0, @res);
+SELECT 'f18',@res;
+CALL f18(1, @res);
+SELECT 'f18',@res;
+CALL f18(2, @res);
+SELECT 'f18',@res;
+DROP PROCEDURE f18;
+
+--echo #
+--echo # Jump inside/outside case block
+--echo #
+DELIMITER $$;
+CREATE or replace procedure f19(lim INT, res OUT VARCHAR)
+AS
+ a INT;
+BEGIN
+ a:=1;
+ case lim
+ when 1 then
+<<lab19_0>>
+ a:=a+1;
+ if (a<10) then
+ goto lab19_0;
+ else
+ goto lab19_1;
+ end if;
+ res:='case branch 19_1';
+ else
+ res:='default branch 18';
+ end case;
+ goto lab19_end;
+<<lab19_1>>
+ res:=a;
+<<lab19_end>>
+ return ;
+END;
+$$
+DELIMITER ;$$
+SET @res='';
+CALL f19(1, @res);
+SELECT 'f19',@res;
+DROP PROCEDURE f19;
+
+DELIMITER $$;
+--echo #
+--echo # Jump outside labeled loop
+--echo #
+CREATE OR REPLACE PROCEDURE f20(res OUT VARCHAR)
+AS
+ a INT := 1;
+BEGIN
+ <<lab>>
+ FOR i IN a..10 LOOP
+ IF i = 5 THEN
+ a:= a+1;
+ goto lab;
+ END IF;
+ END LOOP;
+ res:=a;
+END;
+$$
+DELIMITER ;$$
+CALL f20(@res);
+SELECT 'f20',@res;
+DROP PROCEDURE f20;
+
+DELIMITER $$;
+--echo #
+--echo # Jump (continue) labeled loop
+--echo #
+CREATE OR REPLACE PROCEDURE f23(res OUT VARCHAR)
+AS
+ a INT := 1;
+BEGIN
+ <<lab>>
+ FOR i IN a..10 LOOP
+ IF i = 5 THEN
+ a:= a+1;
+ continue lab;
+ END IF;
+ END LOOP;
+ res:=a;
+END;
+$$
+DELIMITER ;$$
+CALL f23(@res);
+SELECT 'f23',@res;
+DROP PROCEDURE f23;
+
+DELIMITER $$;
+--echo #
+--echo # Two consecutive label (backward jump)
+--echo #
+CREATE OR REPLACE PROCEDURE p24(action IN INT, res OUT varchar) AS
+ a integer;
+BEGIN
+ <<lab1>>
+ <<lab2>>
+ if (action = 1) then
+ res:=res||' '||action;
+ action:=2;
+ goto lab1;
+ end if;
+ if (action = 2) then
+ res:=res||' '||action;
+ action:=3;
+ goto lab2;
+ end if;
+END;
+$$
+DELIMITER ;$$
+call p24(1,@res);
+select 'p24',@res;
+DROP PROCEDURE p24;
+
+DELIMITER $$;
+--echo #
+--echo # Two consecutive label (backward and forward jump)
+--echo #
+CREATE OR REPLACE PROCEDURE p25(action IN INT, res OUT varchar) AS
+ a integer;
+BEGIN
+ if (action = 1) then
+ res:=res||' '||action;
+ action:=2;
+ goto lab2;
+ end if;
+ goto lab_end;
+ <<lab1>>
+ <<lab2>>
+ res:=res||' '||action;
+ if (action = 2) then
+ res:=res||' '||action;
+ action:=3;
+ goto lab1;
+ end if;
+<<lab_end>>
+ null;
+END;
+$$
+DELIMITER ;$$
+call p25(1,@res);
+select 'p25',@res;
+DROP PROCEDURE p25;
+
+
+DELIMITER $$;
+--echo #
+--echo # Two consecutive label, continue to wrong label
+--error ER_SP_LILABEL_MISMATCH
+CREATE OR REPLACE PROCEDURE p26(action IN INT, res OUT varchar) AS
+BEGIN
+ <<lab1>>
+ <<lab2>>
+ FOR i IN 1..10 LOOP
+ continue lab1;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--echo #
+--echo # Consecutive goto label and block label
+--echo #
+CREATE OR REPLACE PROCEDURE p27(action IN INT, res OUT varchar) AS
+BEGIN
+ res:='';
+ <<lab1>>
+ <<lab2>>
+ FOR i IN 1..10 LOOP
+ if (action = 1) then
+ res:=res||' '||action||'-'||i;
+ action:=2;
+ continue lab2;
+ end if;
+ if (action = 2) then
+ res:=res||' '||action||'-'||i;
+ action:='3';
+ goto lab2;
+ end if;
+ if (action = 3) then
+ res:=res||' '||action||'-'||i;
+ action:='4';
+ goto lab1;
+ end if;
+ if (action = 4) then
+ res:=res||' '||action||'-'||i;
+ exit lab2;
+ end if;
+ END LOOP;
+END;
+$$
+
+DELIMITER ;$$
+call p27(1,@res);
+select 'p27',@res;
+DROP PROCEDURE p27;
+
+--echo # ----------------------
+--echo # -- TEST IN FUNCTION --
+--echo # ----------------------
+
+--echo #
+--echo # FUNCTION : Backward jump
+--echo #
+DELIMITER $$;
+CREATE or replace function func1()
+return varchar
+AS
+ p2 varchar(10);
+BEGIN
+ p2:='a';
+<<lab1>>
+ if (p2='a') then
+ p2:=p2||'b';
+ goto lab1;
+ end if;
+ if (p2='ab') then
+ p2:=p2||'c';
+ end if;
+ return p2;
+END;
+$$
+DELIMITER ;$$
+select 'func1',func1();
+DROP function func1;
+
+--echo #
+--echo # FUNCTION : forward jump
+--echo #
+DELIMITER $$;
+CREATE or replace function func2()
+return varchar
+AS
+ p2 varchar(10);
+BEGIN
+ p2:='a';
+ if (p2='a') then
+ goto lab1;
+ end if;
+ p2:='b';
+<<lab1>>
+ return p2;
+END;
+$$
+DELIMITER ;$$
+select 'func2',func2();
+DROP function func2;
+
+--echo # ---------------------
+--echo # -- TEST IN TRIGGER --
+--echo # ---------------------
+
+--echo #
+--echo # TRIGGER : forward jump
+--echo #
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ IF :NEW.a IS NULL
+ THEN
+ :NEW.a:= 15;
+ goto end_trg;
+ END IF;
+ :NEW.a:= 10;
+<<end_trg>>
+ null;
+END;
+$$
+DELIMITER ;$$
+insert into t1 values (1);
+insert into t1 values (null);
+SELECT * FROM t1;
+DROP TRIGGER trg1;
+DROP TABLE t1; \ No newline at end of file
diff --git a/mysql-test/suite/compat/oracle/t/sp-param.inc b/mysql-test/suite/compat/oracle/t/sp-param.inc
new file mode 100644
index 00000000000..35bce8accea
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-param.inc
@@ -0,0 +1,9 @@
+--eval CREATE FUNCTION f1(param $type) RETURN $type AS BEGIN RETURN param; END;
+SHOW CREATE FUNCTION f1;
+
+--eval SELECT LENGTH(f1(REPEAT('a',$length)));
+--eval CREATE TABLE t1 AS SELECT f1(REPEAT('a',$length)) AS a;
+
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP FUNCTION f1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-param.test b/mysql-test/suite/compat/oracle/t/sp-param.test
new file mode 100644
index 00000000000..23203317f50
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-param.test
@@ -0,0 +1,37 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10596 Allow VARCHAR and VARCHAR2 without length as a data type of routine parameters and in RETURN clause
+--echo #
+
+--let type = CHAR
+--let length = 2000
+--source sp-param.inc
+
+--let type = NCHAR
+--let length = 2000
+--source sp-param.inc
+
+--let type = BINARY
+--let length = 2000
+--source sp-param.inc
+
+--let type = VARCHAR
+--let length = 4000
+--source sp-param.inc
+
+--let type = VARCHAR2
+--let length = 4000
+--source sp-param.inc
+
+--let type = NVARCHAR
+--let length = 4000
+--source sp-param.inc
+
+--let type = VARBINARY
+--let length = 4000
+--source sp-param.inc
+
+--let type = RAW
+--let length = 4000
+--source sp-param.inc
diff --git a/mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc b/mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc
new file mode 100644
index 00000000000..14f6f7dfd44
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc
@@ -0,0 +1,6 @@
+--let $query= CREATE PROCEDURE p1() AS var $type; rec ROW(var $type); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END
+--eval $query
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-row.test b/mysql-test/suite/compat/oracle/t/sp-row.test
new file mode 100644
index 00000000000..5d97bf02fa2
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-row.test
@@ -0,0 +1,2377 @@
+SET sql_mode=ORACLE;
+
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+
+--echo #
+--echo # ROW of ROWs is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1()
+AS
+ a ROW(a ROW(a INT));
+BEGIN
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Returning the entire ROW parameter from a function
+--echo #
+# TODO: this should probably return an error at compile time
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURN INT
+AS
+BEGIN
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20));
+DROP FUNCTION f1;
+
+
+
+--echo #
+--echo # ROW as an SP parameter
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURN INT
+AS
+BEGIN
+ RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT,b INT):=(11,21);
+BEGIN
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+SELECT f1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20,30));
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+AS
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+CALL p1(10);
+--error ER_OPERAND_COLUMNS
+CALL p1(ROW(10,20,30));
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP OUT parameter
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT ROW(a INT,b INT))
+AS
+BEGIN
+ a.a:=10;
+ a.b:=20;
+END;
+$$
+CREATE PROCEDURE p2
+AS
+ a ROW(a INT,b INT):=(11,21);
+BEGIN
+ CALL p1(a);
+ SELECT a.a,a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP return value is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE FUNCTION p1() RETURN ROW(a INT)
+AS
+BEGIN
+ RETURN NULL;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Diplicate row field
+--echo #
+DELIMITER $$;
+--error ER_DUP_FIELDNAME
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT, a DOUBLE);
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Bad scalar default value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT, b DOUBLE):= 1;
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Bad ROW default value with a wrong number of fields
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT, b DOUBLE):= ROW(1,2,3);
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Scalar variable vs table alias cause no ambiguity
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT;
+BEGIN
+ -- a.x is a table column here (not a row variable field)
+ SELECT a.x FROM a;
+ SELECT a.x FROM t1 a;
+END;
+$$
+DELIMITER ;$$
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Using the entire ROW variable in select list
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW variable in functions
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing the entire ROW to a scalar value
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT a=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT 1=a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Passing the entire ROW to a stored function
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+ RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+ RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 1 column
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT);
+BEGIN
+ rec:=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 2 columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec:=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW value to a ROW variable with different number of columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec:=ROW(1,2,3);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Returning the entire ROW from a function is not supported yet
+--echo # This syntax would be needed: SELECT f1().x FROM DUAL;
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ rec ROW(a INT);
+BEGIN
+ RETURN rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Using the entire ROW in SELECT..CREATE
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW in LIMIT
+--echo #
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= '10';
+ SELECT * FROM t1 LIMIT rec;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Setting ROW fields using a SET command
+--echo #
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+ a INT;
+BEGIN
+ SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+ SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from a ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec:=ROW(1,2);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from another ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT,b INT);
+ rec2 ROW(a INT,b INT);
+BEGIN
+ rec1:=ROW(1,2);
+ rec2:=rec1;
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to a ROW() function
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:= 1;
+ rec.b:= 2;
+ SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+ SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+ SELECT rec=(NULL,0), rec=ROW(NULL,0);
+ SELECT rec=(NULL,2), rec=ROW(NULL,2);
+ SELECT rec<>(0,0), rec<>ROW(0,0);
+ SELECT rec<>(1,2), rec<>ROW(1,2);
+ SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+ SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+ SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+ SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+ SELECT rec IN ((0,NULL),(1,2));
+ SELECT rec NOT IN ((0,NULL),(1,1));
+ SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to another ROW variable
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec1,rec2,rec3 ROW(a INT,b INT);
+BEGIN
+ rec1.a:= 1;
+ rec1.b:= 2;
+ rec2.a:= 11;
+ rec2.b:= 12;
+ rec3.a:= 11;
+ rec3.b:= 12;
+ SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referencing a non-existing row variable
+--echo #
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1()
+AS
+BEGIN
+ SET a.b=1;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1()
+AS
+BEGIN
+ a.b:=1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Referencing a non-existing row field
+--echo #
+DELIMITER $$;
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT,b INT);
+BEGIN
+ SELECT a.c FROM t1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW and scalar variables with the same name shadowing each other
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT);
+BEGIN
+ a.a:=100;
+ DECLARE
+ a INT:= 200;
+ BEGIN
+ SELECT a;
+ DECLARE
+ a ROW(a INT);
+ BEGIN
+ a.a:=300;
+ SELECT a.a;
+ END;
+ SELECT a;
+ END;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW with good default values
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT,b INT):= (10,20);
+ b ROW(a INT,b INT):= (11,21);
+ c ROW(a INT,b INT):= a;
+BEGIN
+ SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT,b INT):=ROW(10,20);
+BEGIN
+ SELECT * FROM t1 WHERE rec=ROW(a,b);
+ SELECT * FROM t1 WHERE ROW(a,b)=rec;
+ SELECT * FROM t1 WHERE rec=ROW(10,20);
+ SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 10;
+ SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in HAVING clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 10;
+ SELECT * FROM t1 HAVING a=rec.a;
+ SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in LIMIT clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+--error ER_SP_UNDECLARED_VAR
+SELECT 1 FROM t1 LIMIT t1.a;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 10;
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a VARCHAR(10));
+BEGIN
+ rec.a:= '10';
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW fields in select list
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ t1 ROW(a INT);
+BEGIN
+ t1.a:= 10;
+ SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+ SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as insert values
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT, b VARCHAR(10));
+BEGIN
+ rec.a:= 10;
+ rec.b:= 'test';
+ INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as SP out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+ a:= 10;
+ b:= 'test';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+ rec ROW(a INT, b VARCHAR(10));
+BEGIN
+ CALL p1(rec.a, rec.b);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as dynamic SQL out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+ a:= 20;
+ b:= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+ rec ROW(a INT, b VARCHAR(30));
+BEGIN
+ EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as SELECT..INTO targets
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT, b VARCHAR(10));
+BEGIN
+ SELECT 10,'test' INTO rec.a,rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Implicit default NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+BEGIN
+ SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT, b VARCHAR(10)):=(NULL,NULL);
+ rec2 ROW(a INT, b VARCHAR(10)):=rec1;
+BEGIN
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (10,20);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (NULL,20);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (10,NULL);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (NULL,NULL);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing multiple ROW variable declarations
+--echo # This makes sure that fill_field_definitions() is called only once
+--echo # per a ROW field, so create length is not converted to internal length
+--echo # multiple times.
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+BEGIN
+ CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # INT
+--echo #
+
+--let type=INT
+--source sp-row-vs-var.inc
+
+--let type=INT(1)
+--source sp-row-vs-var.inc
+
+--let type=INT(2)
+--source sp-row-vs-var.inc
+
+--let type=INT(3)
+--source sp-row-vs-var.inc
+
+--let type=INT(4)
+--source sp-row-vs-var.inc
+
+--let type=INT(5)
+--source sp-row-vs-var.inc
+
+--let type=INT(6)
+--source sp-row-vs-var.inc
+
+--let type=INT(7)
+--source sp-row-vs-var.inc
+
+--let type=INT(8)
+--source sp-row-vs-var.inc
+
+--let type=INT(9)
+--source sp-row-vs-var.inc
+
+--let type=INT(10)
+--source sp-row-vs-var.inc
+
+--let type=INT(11)
+--source sp-row-vs-var.inc
+
+--let type=INT(12)
+--source sp-row-vs-var.inc
+
+--let type=INT(13)
+--source sp-row-vs-var.inc
+
+--let type=INT(14)
+--source sp-row-vs-var.inc
+
+--let type=INT(20)
+--source sp-row-vs-var.inc
+
+--let type=INT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # TINYINT
+--echo #
+
+--let type=TINYINT
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(1)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(2)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(3)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(4)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(5)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(6)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(7)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(8)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(9)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(10)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(11)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(12)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(13)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(14)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(20)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # SMALLINT
+--echo #
+
+--let type=SMALLINT
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(1)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(2)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(3)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(4)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(5)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(6)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(7)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(8)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(9)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(10)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(11)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(12)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(13)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(14)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(20)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # MEDIUMINT
+--echo #
+
+--let type=MEDIUMINT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(1)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(2)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(3)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(4)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(5)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(6)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(7)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(8)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(9)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(10)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(11)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(12)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(13)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(14)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(20)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # BIGINT
+--echo #
+
+--let type=BIGINT
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(1)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(2)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(3)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(4)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(5)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(6)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(7)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(8)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(9)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(10)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(11)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(12)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(13)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(14)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(20)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # DOUBLE
+--echo #
+
+--let type=DOUBLE
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,1)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,2)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,3)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,4)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,5)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,6)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,7)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,8)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,9)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,10)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,11)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,12)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,13)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,14)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,20)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # VARCHAR
+--echo #
+
+--let type=CHAR
+--source sp-row-vs-var.inc
+
+--let type=BINARY
+--source sp-row-vs-var.inc
+
+--let type=CHAR(1)
+--source sp-row-vs-var.inc
+
+--let type=CHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=NCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=BINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARBINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # TIME
+--echo #
+
+--let type=TIME
+--source sp-row-vs-var.inc
+
+--let type=TIME(1)
+--source sp-row-vs-var.inc
+
+--let type=TIME(2)
+--source sp-row-vs-var.inc
+
+--let type=TIME(3)
+--source sp-row-vs-var.inc
+
+--let type=TIME(4)
+--source sp-row-vs-var.inc
+
+--let type=TIME(5)
+--source sp-row-vs-var.inc
+
+--let type=TIME(6)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # DATETIME
+--echo #
+
+--let type=DATETIME
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(1)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(2)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(3)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(4)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(5)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(6)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # LOB
+--echo #
+
+--let type=TEXT
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT
+--source sp-row-vs-var.inc
+
+--let type=TEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+--echo #
+--echo # MDEV-12133 sql_mode=ORACLE: table%ROWTYPE in variable declarations
+--echo #
+
+--echo #
+--echo # Referring to a table in a non-existing database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec test2.t1%ROWTYPE;
+BEGIN
+ NULL;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a table in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec t1%ROWTYPE;
+BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a table in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec test.t1%ROWTYPE;
+BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a view in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec v1%ROWTYPE;
+BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a view in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec test.v1%ROWTYPE;
+BEGIN
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Checking that all table%ROWTYPE fields are NULL by default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A table%ROWTYPE variable with a ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE DEFAULT ROW(10,'bbb');
+BEGIN
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A table%ROWTYPE variable with an incompatible ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE DEFAULT ROW(10,'bbb','ccc');
+BEGIN
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A table%ROWTYPE variable with a ROW variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 ROW(a INT, b VARCHAR(10)):= ROW(10,'bbb');
+ rec2 t1%ROWTYPE DEFAULT rec1;
+BEGIN
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A ROW variable using a table%ROWTYPE variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE := ROW(10,'bbb');
+ rec2 ROW(a INT, b VARCHAR(10)):= rec1;
+BEGIN
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning table%ROWTYPE variables with a different column count
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+ rec2 t2%ROWTYPE;
+BEGIN
+ rec2:=rec1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+ rec2 t2%ROWTYPE;
+BEGIN
+ rec1:=rec2;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning compatible table%ROWTYPE variables (equal number of fields)
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+ rec2 t2%ROWTYPE;
+BEGIN
+ rec1.a:= 10;
+ rec1.b:= 'bbb';
+ rec2:=rec1;
+ SELECT rec2.x, rec2.y;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between incompatible table%ROWTYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+ rec2 ROW(x INT,y INT,z INT);
+BEGIN
+ rec2.x:= 10;
+ rec2.y:= 20;
+ rec2.z:= 30;
+ rec1:= rec2;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between compatible table%ROWTYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+ rec2 ROW(x INT,y INT);
+BEGIN
+ rec2.x:= 10;
+ rec2.y:= 20;
+ rec1:= rec2;
+ SELECT rec1.a, rec1.b;
+ rec1.a:= 11;
+ rec1.b:= 21;
+ rec2:= rec1;
+ SELECT rec2.x, rec2.y;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning table%ROWTYPE from a ROW expression
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ rec1:= ROW(10,20);
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a table%ROWTYPE variable with a wrong field count
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec2 t2%ROWTYPE;
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ CLOSE cur1;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_WRONG_NO_OF_FETCH_ARGS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a table%ROWTYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec t1%ROWTYPE;
+ CURSOR cur IS SELECT * FROM t1;
+BEGIN
+ OPEN cur;
+ LOOP
+ FETCH cur INTO rec;
+ EXIT WHEN cur%NOTFOUND;
+ SELECT rec.a, rec.b, rec.c, rec.d;
+ INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Fetching a cursor into a table%ROWTYPE variable with different column names
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec2 t2%ROWTYPE;
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.x, rec2.y;
+ CLOSE cur1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a table%ROWTYPE variable, with truncation
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec2 t2%ROWTYPE;
+ CURSOR cur1 IS SELECT * FROM t1;
+BEGIN
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.a, rec2.b;
+ CLOSE cur1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # table%ROWTYPE variables are not allowed in LIMIT
+--echo #
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+AS
+ rec1 t1%ROWTYPE:=(1,2);
+BEGIN
+ SELECT * FROM t1 LIMIT rec1.a;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # table%ROWTYPE variable fields as OUT parameters
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT INT,b OUT VARCHAR(10))
+AS
+BEGIN
+ a:=10;
+ b:='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ CALL p1(rec1.a, rec1.b);
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire table%ROWTYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+ rec1 t1%ROWTYPE:= ROW(10,'bb');
+BEGIN
+ CALL p1(rec1);
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire table%ROWTYPE variable as an OUT parameter
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT ROW(a INT, b VARCHAR(10)))
+AS
+BEGIN
+ a:= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ CALL p1(rec1);
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Assigning a table%ROWTYPE field to an OUT parameter
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1 (res IN OUT INTEGER)
+AS
+ rec1 t1%ROWTYPE:=ROW(10,'b0');
+BEGIN
+ res:=rec1.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1(@res);
+SELECT @res;
+SET @res=NULL;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing Item_splocal_row_field_by_name::print
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec t1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+ EXPLAIN EXTENDED SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Non-existing field
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec t1%ROWTYPE;
+BEGIN
+ SELECT rec.c;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+ALTER TABLE t1 ADD c INT;
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that field names are case insensitive
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec t1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+ SELECT rec.A, rec.B;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that table%ROWTYPE uses temporary tables vs shadowed real tables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec t1%ROWTYPE:=ROW(10,'bb');
+BEGIN
+ SELECT rec.A, rec.B;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TEMPORARY TABLE t1;
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing that the structure of table%ROWTYPE variables is determined at the very beginning and is not changed after ALTER
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ ALTER TABLE t1 ADD c INT;
+ DECLARE
+ rec t1%ROWTYPE; -- this will not have column "c"
+ BEGIN
+ rec.c:=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12291 Allow ROW variables as SELECT INTO targets
+--echo #
+
+
+--echo # ROW variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec1 ROW(a INT, b VARCHAR(32), c DOUBLE);
+BEGIN
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # Multiple ROW variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+ SELECT * FROM t1 INTO rec1, rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # ROW variables working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec1 ROW(a INT, b VARCHAR(32));
+BEGIN
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # table%ROWTYPE variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ SELECT 10,'a','b' FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # Multiple table%ROWTYPE variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ SELECT 10,'a' FROM t1 INTO rec1, rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # table%ROWTYPE working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ rec1 t1%ROWTYPE;
+BEGIN
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # cursor%ROWTYPE variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur1 IS SELECT 10, 'b0', 'c0';
+ rec1 cur1%ROWTYPE;
+BEGIN
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # Multiple cursor%ROWTYPE variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ rec1 cur1%ROWTYPE;
+BEGIN
+ SELECT * FROM t1 INTO rec1, rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # cursor%ROWTYPE working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ rec1 cur1%ROWTYPE;
+BEGIN
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12347 Valgrind reports invalid read errors in Item_field_row::element_index_by_name
+--echo #
+
+# An additional test for MDEV-12347, to make sure that
+# Column_definition::interval creates a permanent copy of TYPELIB on
+# the memory root when processing %ROWTYPE for a table with ENUM/SET column,
+# rather than reuses the TYPELIB from table->field[i], which is freed in the
+# end of sp_rcontext::resolve_table_rowtype_ref().
+
+CREATE TABLE t1 (a INT, b ENUM('b0','b1','b12','b3'));
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ DECLARE
+ rec t1%ROWTYPE;
+ BEGIN
+ rec.b:='b0';
+ SELECT rec.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT, b SET('b0','b1','b12','b3'));
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ DECLARE
+ rec t1%ROWTYPE;
+ BEGIN
+ rec.b:='b0';
+ SELECT rec.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-13273 Confusion between table alias and ROW type variable
+--echo #
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a INT;
+ b INT;
+BEGIN
+ -- a.c1 is a table column
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 0;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a ROW (c1 INT, c2 INT) := ROW(101,102);
+ b INT;
+BEGIN
+ -- a.c1 is a ROW variable field
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 102;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1%ROWTYPE := ROW (10,20);
+ b INT;
+BEGIN
+ -- a.c1 is a ROW variable field
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 20;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ CURSOR cur1 IS SELECT * FROM t1;
+ a cur1%ROWTYPE := ROW (10,20);
+ b INT;
+BEGIN
+ -- a.c1 is a ROW variable field
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 20;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-security.test b/mysql-test/suite/compat/oracle/t/sp-security.test
new file mode 100644
index 00000000000..1732c0b80db
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-security.test
@@ -0,0 +1,345 @@
+--source include/not_embedded.inc
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+--echo #
+
+
+--echo #
+--echo # Initiation:
+--echo # - creating database db1
+--echo # - creating user user1 with access rights to db1
+--echo #
+
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (a INT, b VARCHAR(10));
+
+CREATE USER user1;
+
+GRANT ALL PRIVILEGES ON test.* TO user1;
+
+connect (conn1,localhost,user1,,test);
+SET sql_mode=ORACLE;
+
+SELECT database();
+SELECT user();
+
+--echo #
+--echo # Making sure that user1 does not have privileges to db1.t1
+--echo #
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW CREATE TABLE db1.t1;
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW FIELDS IN db1.t1;
+
+
+--echo #
+--echo # Trigger: using %TYPE with a table we don't have access to
+--echo #
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+DELIMITER $$;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+ DECLARE b db1.t1.b%TYPE := 20;
+ BEGIN
+ :NEW.b := 10;
+ END;
+END
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Stored procedure: Using %TYPE for with a table that we don't have access to
+--echo # DEFINER user1, SQL SECURITY DEFAULT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a db1.t1.a%TYPE := 10;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a db1.t1%ROWTYPE;
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Stored procedure: Using %TYPE for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY INVOKER
+--echo #
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+AS
+ a db1.t1.a%TYPE := 10;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+AS
+ a db1.t1%ROWTYPE;
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Stored procedure: Using %TYPE for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY DEFINER
+--echo #
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+AS
+ a db1.t1.a%TYPE := 10;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+CALL p1;
+DROP PROCEDURE p1;
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+AS
+ a db1.t1%ROWTYPE;
+BEGIN
+ a.a:= 10;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Stored function: Using %TYPE for with a table that we don't have access to
+--echo # DEFINER user1, SQL SECURITY DEFAULT
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN INT
+AS
+ a db1.t1.a%TYPE:=0;
+BEGIN
+ RETURN OCTET_LENGTH(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT f1();
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Stored function: Using %TYPE for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY INVOKER
+--echo #
+
+connection default;
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN INT
+SQL SECURITY INVOKER
+AS
+ a db1.t1.a%TYPE:=0;
+BEGIN
+ RETURN OCTET_LENGTH(a);
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT f1();
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Stored function: Using %TYPE for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY DEFINER
+--echo #
+
+connection default;
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN INT
+SQL SECURITY DEFINER
+AS
+ a db1.t1.a%TYPE:=0;
+BEGIN
+ RETURN OCTET_LENGTH(a);
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+SELECT f1();
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+connection default;
+GRANT SELECT (a) ON db1.t1 TO user1;
+connection conn1;
+
+--echo #
+--echo # Making sure that user1 has access to db1.t1.a, but not to db1.t1.b
+--echo #
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW CREATE TABLE db1.t1;
+SHOW FIELDS IN db1.t1;
+
+--echo #
+--echo # Trigger: Per-column privileges
+--echo #
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+# %TYPE reference using a column we have access to
+DELIMITER $$;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+ DECLARE a db1.t1.a%TYPE := 20;
+ BEGIN
+ :NEW.b := 10;
+ END;
+END
+$$
+DELIMITER ;$$
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+# %TYPE reference using a column that we don't have access to
+DELIMITER $$;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+ DECLARE b db1.t1.b%TYPE := 20;
+ BEGIN
+ :NEW.b := 10;
+ END;
+END
+$$
+DELIMITER ;$$
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+
+--echo #
+--echo # Stored procedure: Per-column privileges
+--echo # DEFINER user1, SQL SECURITY DEFAULT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a db1.t1.a%TYPE := 10;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ b db1.t1.b%TYPE := 10;
+BEGIN
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+--error ER_COLUMNACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ b db1.t1%ROWTYPE;
+BEGIN
+ b.b:=10;
+ SELECT b.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_COLUMNACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Clean up
+--echo #
+disconnect conn1;
+connection default;
+
+DROP USER user1;
+DROP DATABASE db1;
+
+--echo #
+--echo # End of MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+--echo #
diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test
new file mode 100644
index 00000000000..4717ebef8eb
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp.test
@@ -0,0 +1,2133 @@
+SET sql_mode=ORACLE;
+
+--echo # Testing routines with no parameters
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+AS
+BEGIN
+ RETURN 10;
+END;
+/
+DELIMITER ;/
+--vertical_results
+SHOW CREATE FUNCTION f1;
+--horizontal_results
+SELECT f1();
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ SET @a=10;
+END;
+/
+DELIMITER ;/
+--vertical_results
+SHOW CREATE PROCEDURE p1;
+--horizontal_results
+SET @a=0;
+CALL p1();
+SELECT @a;
+DROP PROCEDURE p1;
+
+--echo # Testing ":=" to set the default value of a variable
+DELIMITER /;
+CREATE FUNCTION f1 () RETURN NUMBER(10) AS
+ a NUMBER(10) := 10;
+BEGIN
+ DECLARE
+ b NUMBER(10) DEFAULT 3;
+ BEGIN
+ RETURN a+b;
+ END;
+END;
+/
+DELIMITER ;/
+SELECT f1();
+DROP FUNCTION f1;
+
+--echo # Testing labels
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT) RETURN CLOB AS
+BEGIN
+ <<label1>>
+ BEGIN
+ IF a = 1 THEN
+ LEAVE label1;
+ END IF;
+ RETURN 'IS NOT 1';
+ END label1;
+ RETURN 'IS 1';
+END;
+/
+DELIMITER ;/
+SELECT f1(1);
+SELECT f1(2);
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT) RETURN INT IS
+BEGIN
+ <<label1>>
+ LOOP
+ IF a = 2 THEN
+ LEAVE label1;
+ END IF;
+ SET a= a-1;
+ END LOOP;
+ RETURN a;
+END;
+/
+DELIMITER ;/
+SELECT f1(4);
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT) RETURN INT AS
+BEGIN
+ <<label1>>
+ WHILE a>0 LOOP
+ IF a = 2 THEN
+ LEAVE label1;
+ END IF;
+ SET a= a-1;
+ END LOOP label1;
+ RETURN a;
+END;
+/
+DELIMITER ;/
+SELECT f1(4);
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT) RETURN INT AS
+BEGIN
+ <<label1>>
+ REPEAT
+ IF a = 2 THEN
+ LEAVE label1;
+ END IF;
+ SET a= a-1;
+ UNTIL a=0 END REPEAT;
+ RETURN a;
+END;
+/
+DELIMITER ;/
+SELECT f1(4);
+DROP FUNCTION f1;
+
+--echo # Testing IN/OUT/INOUT
+
+DELIMITER /;
+CREATE PROCEDURE p1 (p1 IN VARCHAR2(10), p2 OUT VARCHAR2(10)) AS
+BEGIN
+ SET p1='p1new';
+ SET p2='p2new';
+END;
+/
+DELIMITER ;/
+SET @p1='p1', @p2='p2';
+CALL p1(@p1, @p2);
+SELECT @p1, @p2;
+DROP PROCEDURE p1;
+
+--echo # Testing Oracle-style assigment
+DELIMITER /;
+CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10)) AS
+BEGIN
+ p1:= 'p1new';
+END;
+/
+DELIMITER ;/
+SET @p1='p1';
+CALL p1(@p1);
+SELECT @p1;
+DROP PROCEDURE p1;
+
+--echo # Testing that NULL is a valid statement
+DELIMITER /;
+CREATE PROCEDURE p1(a INT) AS
+BEGIN
+ NULL;
+END;
+/
+DELIMITER ;/
+DROP PROCEDURE p1;
+
+DELIMITER /;
+CREATE PROCEDURE p1(a INT) AS
+ a INT:=10;
+BEGIN
+ IF a=10 THEN NULL; ELSE NULL; END IF;
+END;
+/
+DELIMITER ;/
+DROP PROCEDURE p1;
+
+
+--echo # Testing that (some) keyword_sp are allowed in Oracle-style assignments
+DELIMITER /;
+CREATE PROCEDURE p1 (action OUT INT) AS BEGIN action:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (clob OUT INT) AS BEGIN clob:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (enum OUT INT) AS BEGIN enum:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (via OUT INT) AS BEGIN via:=10; END;/
+DROP PROCEDURE p1/
+DELIMITER ;/
+
+--echo # Testing keyword_directly_assignable
+DELIMITER /;
+CREATE PROCEDURE p1 (ascii OUT INT) AS BEGIN ascii:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (backup OUT INT) AS BEGIN backup:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (binlog OUT INT) AS BEGIN binlog:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (byte OUT INT) AS BEGIN byte:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (cache OUT INT) AS BEGIN cache:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (checksum OUT INT) AS BEGIN checksum:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (checkpoint OUT INT) AS BEGIN checkpoint:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_add OUT INT) AS BEGIN column_add:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_check OUT INT) AS BEGIN column_check:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_create OUT INT) AS BEGIN column_create:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_delete OUT INT) AS BEGIN column_delete:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (column_get OUT INT) AS BEGIN column_get:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (deallocate OUT INT) AS BEGIN deallocate:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (examined OUT INT) AS BEGIN examined:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (execute OUT INT) AS BEGIN execute:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (flush OUT INT) AS BEGIN flush:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (format OUT INT) AS BEGIN format:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (get OUT INT) AS BEGIN get:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (help OUT INT) AS BEGIN help:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (host OUT INT) AS BEGIN host:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (install OUT INT) AS BEGIN install:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (option OUT INT) AS BEGIN option:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (options OUT INT) AS BEGIN options:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (owner OUT INT) AS BEGIN owner:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (parser OUT INT) AS BEGIN parser:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (port OUT INT) AS BEGIN port:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (prepare OUT INT) AS BEGIN prepare:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (remove OUT INT) AS BEGIN remove:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (reset OUT INT) AS BEGIN reset:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (restore OUT INT) AS BEGIN restore:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (security OUT INT) AS BEGIN security:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (server OUT INT) AS BEGIN server:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (signed OUT INT) AS BEGIN signed:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (socket OUT INT) AS BEGIN socket:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (slave OUT INT) AS BEGIN slave:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (slaves OUT INT) AS BEGIN slaves:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (soname OUT INT) AS BEGIN soname:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (start OUT INT) AS BEGIN start:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (stop OUT INT) AS BEGIN stop:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (stored OUT INT) AS BEGIN stored:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (unicode OUT INT) AS BEGIN unicode:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (uninstall OUT INT) AS BEGIN uninstall:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (upgrade OUT INT) AS BEGIN upgrade:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (wrapper OUT INT) AS BEGIN wrapper:=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (xa OUT INT) AS BEGIN xa:=10; END;/
+DROP PROCEDURE p1/
+DELIMITER ;/
+
+
+--echo # Testing that keyword_directly_not_assignable does not work in :=
+DELIMITER /;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 (commit OUT INT) AS BEGIN commit:=10; END;/
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 (rollback OUT INT) AS BEGIN rollback:=10; END;/
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1 (shutdown OUT INT) AS BEGIN shutdown:=10; END;/
+DELIMITER ;/
+
+
+--echo # Testing that keyword_directly_not_assignable works in SET statements.
+DELIMITER /;
+CREATE PROCEDURE p1 (contains OUT INT) AS BEGIN SET contains=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (language OUT INT) AS BEGIN SET language=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (no OUT INT) AS BEGIN SET no=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (charset OUT INT) AS BEGIN SET charset=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (do OUT INT) AS BEGIN SET do=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (repair OUT INT) AS BEGIN SET repair=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (handler OUT INT) AS BEGIN SET handler=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (open OUT INT) AS BEGIN SET open=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (close OUT INT) AS BEGIN SET close=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (savepoint OUT INT) AS BEGIN SET savepoint=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (truncate OUT INT) AS BEGIN SET truncate=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (begin OUT INT) AS BEGIN SET begin=10; END;/
+DROP PROCEDURE p1/
+CREATE PROCEDURE p1 (end OUT INT) AS BEGIN SET end=10; END;/
+DROP PROCEDURE p1/
+DELIMITER ;/
+
+--echo # Testing that keyword_directly_not_assignable works in table/column names
+CREATE TABLE contains (contains INT);
+DROP TABLE contains;
+CREATE TABLE language (language INT);
+DROP TABLE language;
+CREATE TABLE no (no INT);
+DROP TABLE no;
+CREATE TABLE charset (charset INT);
+DROP TABLE charset;
+CREATE TABLE do (do INT);
+DROP TABLE do;
+CREATE TABLE repair (repair INT);
+DROP TABLE repair;
+CREATE TABLE handler (handler INT);
+DROP TABLE handler;
+CREATE TABLE open (open INT);
+DROP TABLE open;
+CREATE TABLE close (close INT);
+DROP TABLE close;
+CREATE TABLE savepoint (savepoint INT);
+DROP TABLE savepoint;
+CREATE TABLE truncate (truncate INT);
+DROP TABLE truncate;
+CREATE TABLE begin (begin INT);
+DROP TABLE begin;
+CREATE TABLE end (end INT);
+DROP TABLE end;
+
+--echo # Testing ELSIF
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN CLOB
+AS
+BEGIN
+ IF a=1 THEN RETURN 'a is 1';
+ ELSIF a=2 THEN RETURN 'a is 2';
+ ELSE RETURN 'a is unknown';
+ END IF;
+END;
+/
+DELIMITER ;/
+SELECT f1(2) FROM DUAL;
+DROP FUNCTION f1;
+
+
+
+--echo # Testing top-level declarations
+DELIMITER /;
+CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
+AS
+ p2 VARCHAR(10);
+BEGIN
+ p2:='p1new';
+ p1:=p2;
+END;
+/
+DELIMITER ;/
+SET @p1='p1';
+CALL p1(@p1);
+SELECT @p1;
+DROP PROCEDURE p1;
+
+DELIMITER /;
+CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURN VARCHAR(20)
+AS
+ p2 VARCHAR(10);
+BEGIN
+ p2:='new';
+ RETURN CONCAT(p1, p2);
+END;
+/
+DELIMITER ;/
+SET @p1='p1';
+SELECT f1(@p1);
+DROP FUNCTION f1;
+
+--echo # Testing non-top declarations
+
+DELIMITER /;
+CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
+AS
+BEGIN
+ DECLARE
+ p2 VARCHAR(10);
+ BEGIN
+ p2:='p1new';
+ p1:=p2;
+ END;
+ DECLARE
+ t1 VARCHAR(10);
+ t2 VARCHAR(10);
+ BEGIN
+ END;
+END;
+/
+DELIMITER ;/
+SET @p1='p1';
+CALL p1(@p1);
+SELECT @p1;
+DROP PROCEDURE p1;
+
+DELIMITER /;
+CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURN VARCHAR(20)
+AS
+BEGIN
+ DECLARE
+ p2 VARCHAR(10);
+ BEGIN
+ p2:='new';
+ RETURN CONCAT(p1, p2);
+ END;
+ DECLARE
+ t1 VARCHAR(10);
+ t2 VARCHAR(10);
+ BEGIN
+ END;
+END;
+/
+DELIMITER ;/
+SET @p1='p1';
+SELECT f1(@p1);
+DROP FUNCTION f1;
+
+
+--echo # Testing exceptions
+
+CREATE TABLE t1 (c1 INT);
+
+DELIMITER /;
+
+CREATE PROCEDURE sp1 (p1 IN VARCHAR2(20), p2 OUT VARCHAR2(30))
+IS
+ v1 INT;
+BEGIN
+ SELECT c1 INTO v1 FROM t1;
+ p2 := p1;
+EXCEPTION
+ WHEN NOT FOUND THEN
+ BEGIN
+ p2 := 'def';
+ END;
+END;
+/
+
+DELIMITER ;/
+
+CALL sp1('abc', @a);
+SELECT @a;
+
+DROP PROCEDURE sp1;
+DROP TABLE t1;
+
+
+DELIMITER /;
+CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT)
+IS
+BEGIN
+ SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!';
+ v:= 223;
+EXCEPTION
+ WHEN 30001 THEN
+ BEGIN
+ v:= 113;
+ END;
+END;
+/
+DELIMITER ;/
+SET @v=10;
+CALL sp1(@v, 30001);
+--error 30002
+CALL sp1(@v, 30002);
+SELECT @v;
+DROP PROCEDURE sp1;
+
+
+DELIMITER /;
+CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT)
+IS
+BEGIN
+ BEGIN
+ BEGIN
+ SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!';
+ v:= 223;
+ EXCEPTION
+ WHEN 30001 THEN
+ BEGIN
+ v:= 113;
+ END;
+ END;
+ END;
+END;
+/
+DELIMITER ;/
+SET @v=10;
+CALL sp1(@v, 30001);
+SELECT @v;
+SET @v=10;
+--error 30002
+CALL sp1(@v, 30002);
+SELECT @v;
+DROP PROCEDURE sp1;
+
+
+--echo #
+--echo # Testing EXIT statement
+--echo #
+
+DELIMITER /;
+--error ER_SP_LILABEL_MISMATCH
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ EXIT;
+END;
+/
+DELIMITER ;/
+
+
+DELIMITER /;
+--error ER_SP_LILABEL_MISMATCH
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ <<lable1>>
+ BEGIN
+ <<label2>>
+ LOOP
+ EXIT label1;
+ END LOOP;
+ END;
+END;
+/
+DELIMITER ;/
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ LOOP
+ LOOP
+ i:= i + 1;
+ IF i >= 5 THEN
+ EXIT;
+ END IF;
+ END LOOP;
+ i:= i + 100;
+ EXIT;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ <<label1>>
+ LOOP
+ <<label2>>
+ LOOP
+ i:= i + 1;
+ IF i >= 5 THEN
+ EXIT label2;
+ END IF;
+ END LOOP;
+ i:= i + 100;
+ EXIT;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ <<label1>>
+ LOOP
+ <<label2>>
+ LOOP
+ i:= i + 1;
+ IF i >= 5 THEN
+ EXIT label1;
+ END IF;
+ END LOOP;
+ i:= i + 100;
+ EXIT;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ LOOP
+ i:= i + 1;
+ EXIT WHEN i >=5;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ <<label1>>
+ LOOP
+ <<label2>>
+ LOOP
+ i:= i + 1;
+ EXIT label2 WHEN i >= 5;
+ END LOOP;
+ i:= i + 100;
+ EXIT;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+IS
+ i INT := 0;
+BEGIN
+ <<label1>>
+ LOOP
+ <<label2>>
+ LOOP
+ i:= i + 1;
+ EXIT label1 WHEN i >= 5;
+ END LOOP;
+ i:= i + 100;
+ EXIT;
+ END LOOP;
+ RETURN i;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing CURSOR declaration
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+AS
+ v_a INT:=10;
+ CURSOR c IS SELECT a FROM t1;
+BEGIN
+ OPEN c;
+ FETCH c INTO v_a;
+ CLOSE c;
+ RETURN v_a;
+EXCEPTION
+ WHEN OTHERS THEN RETURN -1;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo # Testing RETURN in procedures
+
+DELIMITER /;
+--error ER_SP_BADRETURN
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+ RETURN 10;
+END;
+/
+DELIMITER ;/
+
+DELIMITER /;
+--error ER_PARSE_ERROR
+CREATE FUNCTION f1 (a INT) RETURN INT
+AS
+BEGIN
+ RETURN;
+END;
+/
+DELIMITER ;/
+
+DELIMITER /;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+ IF a < 10 THEN
+ BEGIN
+ a:= a - 1;
+ RETURN;
+ END;
+ END IF;
+ a:= a + 1;
+EXCEPTION
+ WHEN OTHERS THEN RETURN;
+END;
+/
+DELIMITER ;/
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+SET @v=9;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+DELIMITER /;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+BEGIN
+ DROP TABLE t1_non_existent;
+EXCEPTION
+ WHEN OTHERS THEN
+ BEGIN
+ a:= 100;
+ RETURN;
+ END;
+END;
+/
+DELIMITER ;/
+SET @v=10;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # Testing WHILE loop
+
+DELIMITER /;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+ i INT:= 1;
+ j INT:= 3;
+BEGIN
+ WHILE i<=j
+ LOOP
+ a:= a + i;
+ i:= i + 1;
+ END LOOP;
+END;
+/
+DELIMITER ;/
+SET @v=0;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+DELIMITER /;
+CREATE PROCEDURE p1 (a IN OUT INT)
+AS
+ i INT:= 1;
+ j INT:= 3;
+BEGIN
+ <<label>>
+ WHILE i<=j
+ LOOP
+ a:= a + i;
+ i:= i + 1;
+ END LOOP label;
+END;
+/
+DELIMITER ;/
+SET @v=0;
+CALL p1(@v);
+SELECT @v;
+DROP PROCEDURE p1;
+
+
+--echo # Testing the FOR loop statement
+
+CREATE TABLE t1 (a INT);
+DELIMITER /;
+FOR i IN 1..3
+LOOP
+ INSERT INTO t1 VALUES (i);
+END LOOP;
+/
+DELIMITER ;/
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+DELIMITER /;
+--error ER_PARSE_ERROR
+CREATE FUNCTION f1 (lower_bound INT, upper_bound INT, lim INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ FOR i IN lower_bound . . upper_bound
+ LOOP
+ NULL
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+
+
+DELIMITER /;
+CREATE FUNCTION f1 (lower_bound INT, upper_bound INT, lim INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ FOR i IN lower_bound .. upper_bound
+ LOOP
+ total:= total + i;
+ IF i = lim THEN
+ EXIT;
+ END IF;
+ -- Bounds are calculated only once.
+ -- The below assignments have no effect on the loop condition
+ lower_bound:= 900;
+ upper_bound:= 1000;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(1, 3, 100) FROM DUAL;
+SELECT f1(1, 3, 2) FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ FOR i IN 1 .. 5
+ LOOP
+ total:= total + 1000;
+ FOR j IN 1 .. 5
+ LOOP
+ total:= total + 1;
+ IF j = 3 THEN
+ EXIT; -- End the internal loop
+ END IF;
+ END LOOP;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1() FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT, b INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ FOR i IN REVERSE a..1
+ LOOP
+ total:= total + i;
+ IF i = b THEN
+ EXIT;
+ END IF;
+ END LOOP;
+ RETURN total;
+END
+/
+DELIMITER ;/
+SELECT f1(3, 100) FROM DUAL;
+SELECT f1(3, 2) FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing labeled FOR LOOP statement
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT, limita INT, b INT, limitb INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ <<la>>
+ FOR ia IN 1 .. a
+ LOOP
+ total:= total + 1000;
+ <<lb>>
+ FOR ib IN 1 .. b
+ LOOP
+ total:= total + 1;
+ EXIT lb WHEN ib = limitb;
+ EXIT la WHEN ia = limita;
+ END LOOP lb;
+ END LOOP la;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(1, 1, 1, 1) FROM DUAL;
+SELECT f1(1, 2, 1, 2) FROM DUAL;
+SELECT f1(2, 1, 2, 1) FROM DUAL;
+SELECT f1(2, 1, 2, 2) FROM DUAL;
+SELECT f1(2, 2, 2, 2) FROM DUAL;
+SELECT f1(2, 3, 2, 3) FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing labeled ITERATE in a labeled FOR LOOP statement
+
+DELIMITER /;
+CREATE FUNCTION f1 (a INT, b INT, blim INT) RETURN INT
+AS
+ total INT := 0;
+BEGIN
+ <<la>>
+ FOR ia IN 1 .. a
+ LOOP
+ total:= total + 1000;
+ DECLARE
+ ib INT:= 1;
+ BEGIN
+ WHILE ib <= b
+ LOOP
+ IF ib > blim THEN
+ ITERATE la;
+ END IF;
+ ib:= ib + 1;
+ total:= total + 1;
+ END LOOP;
+ END;
+ END LOOP la;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(3,3,0), f1(3,3,1), f1(3,3,2), f1(3,3,3), f1(3,3,4) FROM DUAL;
+DROP FUNCTION f1;
+
+
+--echo # Testing CONTINUE statement
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ FOR i IN 1 .. a
+ LOOP
+ IF i=5 THEN
+ CONTINUE;
+ END IF;
+ total:= total + 1;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ <<lj>>
+ FOR j IN 1 .. 2
+ LOOP
+ FOR i IN 1 .. a
+ LOOP
+ IF i=5 THEN
+ CONTINUE lj;
+ END IF;
+ total:= total + 1;
+ END LOOP;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(3), f1(4), f1(5) FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+BEGIN
+ <<lj>>
+ FOR j IN 1 .. 2
+ LOOP
+ FOR i IN 1 .. a
+ LOOP
+ CONTINUE lj WHEN i=5;
+ total:= total + 1;
+ END LOOP;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(3), f1(4), f1(5) FROM DUAL;
+DROP FUNCTION f1;
+
+
+DELIMITER /;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ total INT:= 0;
+ i INT:= 1;
+BEGIN
+ WHILE i <= a
+ LOOP
+ i:= i + 1;
+ IF i=6 THEN
+ CONTINUE;
+ END IF;
+ total:= total + 1;
+ END LOOP;
+ RETURN total;
+END;
+/
+DELIMITER ;/
+SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
+DROP FUNCTION f1;
+
+--echo #
+--echo # Testing behaviour of unknown identifiers in EXIT and CONTINUE statements
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ LOOP
+ EXIT WHEN unknown_ident IS NULL;
+ END LOOP;
+END$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ <<label>>
+ LOOP
+ EXIT label WHEN unknown_ident IS NULL;
+ END LOOP;
+END$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ LOOP
+ CONTINUE WHEN unknown_ident IS NULL;
+ END LOOP;
+END$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ <<label>>
+ LOOP
+ CONTINUE label WHEN unknown_ident IS NULL;
+ END LOOP;
+END$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT
+--echo #
+
+EXPLAIN EXTENDED SELECT sql%rowcount;
+CREATE TABLE t1 AS SELECT SQL%ROWCOUNT;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # UPDATE
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ UPDATE t1 SET a=30;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ UPDATE t1 SET a=30;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # DELETE
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ DELETE FROM t1;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ DELETE FROM t1;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # SELECT ... INTO var FROM ... - one row found
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ va INT;
+BEGIN
+ SELECT a INTO va FROM t1 LIMIT 1;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # SELECT ... INTO var FROM ... - no rows found
+--echo #
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ va INT;
+BEGIN
+ SELECT a INTO va FROM t1;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ va INT;
+BEGIN
+ SELECT a INTO va FROM t1;
+ SELECT SQL%ROWCOUNT;
+EXCEPTION
+ WHEN NO_DATA_FOUND THEN SELECT SQL%ROWCOUNT||' (EXCEPTION)';
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # SELECT ... INTO var FROM ... - multiple rows found
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ va INT:=1;
+BEGIN
+ SELECT a INTO va FROM t1;
+ SELECT SQL%ROWCOUNT;
+EXCEPTION
+ WHEN TOO_MANY_ROWS THEN SELECT SQL%ROWCOUNT||' (EXCEPTION) va='||va;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+
+--echo #
+--echo # INSERT INTO t2 SELECT ...
+--echo #
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+INSERT INTO t1 VALUES (10);
+INSERT INTO t1 VALUES (20);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ INSERT INTO t2 SELECT * FROM t1;
+ SELECT SQL%ROWCOUNT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1, t2;
+
+--echo #
+--echo # End of MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT
+--echo #
+
+--echo #
+--echo # MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+--echo #
+
+--echo #
+--echo # Missing table
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE;
+BEGIN
+ NULL;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Missing column
+--echo #
+
+CREATE TABLE t1 (b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE;
+BEGIN
+ NULL;
+END;
+$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # One %TYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE;
+BEGIN
+ a:= 123;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Two %TYPE variables, with a truncation warning on assignment
+--echo #
+
+CREATE TABLE t1 (a TINYINT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE;
+ b t1.b%TYPE;
+BEGIN
+ a:= 200;
+ b:= 200;
+ SELECT a, b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %TYPE variables for fields with various attributes
+--echo #
+
+CREATE TABLE t1 (
+ id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ a TINYINT NOT NULL,
+ b INT NOT NULL,
+ ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ UNIQUE(a)
+);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ id t1.id%TYPE;
+ a t1.a%TYPE;
+ b t1.b%TYPE;
+ ts t1.ts%TYPE;
+BEGIN
+ SELECT id, a, b, ts;
+ CREATE TABLE t2 AS SELECT id, a, b, ts;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %TYPE + virtual columns
+--echo #
+
+#
+# TODO: Changing 'a + 10' to 'a mod 10' make it fail, because
+# it's Item::print() returns 'a % 10' which makes grammar conflict
+# with cursor attributes
+
+CREATE TABLE t1 (
+ a INT NOT NULL,
+ b VARCHAR(32),
+ c INT AS (a + 10) VIRTUAL,
+ d VARCHAR(5) AS (left(b,5)) PERSISTENT
+);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ c t1.c%TYPE;
+ d t1.d%TYPE;
+BEGIN
+ SELECT c, d;
+ CREATE TABLE t2 AS SELECT c, d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %TYPE + the ZEROFILL attribute
+--echo #
+
+CREATE TABLE t1 (
+ dz DECIMAL(10,3) ZEROFILL
+);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ dzr t1.dz%TYPE := 10;
+ dzt DECIMAL(10,3) ZEROFILL := 10;
+BEGIN
+ SELECT dzr, dzt;
+ CREATE TABLE t2 AS SELECT dzr,dzt;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Temporary tables shadow real tables for %TYPE purposes
+--echo #
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('t1');
+CREATE TEMPORARY TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE:=11;
+BEGIN
+ CREATE TABLE t2 AS SELECT a;
+END;
+$$
+DELIMITER ;$$
+--echo #
+--echo # Should use INT(11) as %TYPE, as in the temporary table
+--echo #
+CALL p1();
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+SELECT * FROM t1;
+DROP TEMPORARY TABLE t1;
+SELECT * FROM t1;
+--echo #
+--echo # Should use VARCHAR(10) as %TYPE, as in the real table
+--echo #
+CALL p1();
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # t1.a%TYPE searches for "t1" in the current database
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE:=11;
+BEGIN
+ CREATE TABLE test.t2 AS SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # This interprets t1.a%TYPE as VARCHAR(10), as in test.t1.a
+--echo #
+
+USE test;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+DROP TABLE test.t2;
+
+--echo #
+--echo # This interprets t1.a%TYPE as INT, as in test1.t1.a
+--echo #
+
+USE test1;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+DROP TABLE test.t2;
+
+--echo #
+--echo # Error if there is no an active database
+--echo #
+
+DROP DATABASE test1;
+--error ER_NO_DB_ERROR
+CALL test.p1();
+
+USE test;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # A reference to a table in a non-existing database
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a test1.t1.a%TYPE;
+BEGIN
+ CREATE TABLE t1 AS SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A reference to a table in a different database
+--echo #
+CREATE TABLE t1(a INT);
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a t1.a%TYPE;
+ b test1.t1.a%TYPE;
+BEGIN
+ CREATE TABLE t2 AS SELECT a,b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+SHOW CREATE TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP DATABASE test1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Using a table before it appears in a %TYPE declaration + multiple %TYPE declarations
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 (a,b) VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ INSERT INTO t1 (a,b) VALUES (11, 'b11');
+ SELECT * FROM t1;
+ DECLARE
+ va t1.a%TYPE:= 30;
+ vb t1.b%TYPE:= 'b30';
+ BEGIN
+ INSERT INTO t1 (a,b) VALUES (12,'b12');
+ SELECT * FROM t1;
+ INSERT INTO t1 (a,b) VALUES (va, vb);
+ SELECT * FROM t1;
+ END;
+ DECLARE
+ va t1.a%TYPE:= 40;
+ vb t1.b%TYPE:= 'b40';
+ BEGIN
+ INSERT INTO t1 (a,b) VALUES (va,vb);
+ SELECT * FROM t1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # %TYPE variables + TABLE vs VIEW
+--echo #
+
+CREATE TABLE t1 (
+ bit6 BIT(6),
+ bit7 BIT(7),
+ bit8 BIT(8),
+ i1 TINYINT,
+ i2 SMALLINT,
+ i3 MEDIUMINT,
+ i4 INT,
+ i8 BIGINT,
+ ff FLOAT,
+ fd DOUBLE,
+ cc CHAR(10),
+ cv VARCHAR(10),
+ cvu VARCHAR(10) CHARACTER SET utf8,
+ t1 TINYTEXT,
+ t2 TEXT,
+ t3 MEDIUMTEXT,
+ t4 LONGTEXT,
+ enum1 ENUM('a','b','c'),
+ set1 SET('a','b','c'),
+ blob1 TINYBLOB,
+ blob2 BLOB,
+ blob3 MEDIUMBLOB,
+ blob4 LONGBLOB,
+ yy YEAR,
+ dd DATE,
+ tm0 TIME,
+ tm3 TIME(3),
+ tm6 TIME(6),
+ dt0 DATETIME,
+ dt3 DATETIME(3),
+ dt6 DATETIME(6),
+ ts0 TIMESTAMP,
+ ts3 TIMESTAMP(3),
+ ts6 TIMESTAMP(6),
+ dc100 DECIMAL(10,0),
+ dc103 DECIMAL(10,3),
+ dc209 DECIMAL(20,9)
+);
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1(command enum('create','select'))
+AS
+ bit6 t1.bit6%TYPE := 0x30;
+ bit7 t1.bit7%TYPE := 0x41;
+ bit8 t1.bit8%TYPE := 0x7E;
+ i1 t1.i1%TYPE := 11;
+ i2 t1.i2%TYPE := 12;
+ i3 t1.i3%TYPE := 13;
+ i4 t1.i4%TYPE := 14;
+ i8 t1.i8%TYPE := 18;
+ ff t1.ff%TYPE := 21;
+ fd t1.fd%TYPE := 22;
+ cc t1.cc%TYPE := 'char';
+ cv t1.cv%TYPE := 'varchar';
+ cvu t1.cvu%TYPE := 'varcharu8';
+ t1 t1.t1%TYPE := 'text1';
+ t2 t1.t2%TYPE := 'text2';
+ t3 t1.t3%TYPE := 'text3';
+ t4 t1.t4%TYPE := 'text4';
+ enum1 t1.enum1%TYPE := 'b';
+ set1 t1.set1%TYPE := 'a,c';
+ blob1 t1.blob1%TYPE := 'blob1';
+ blob2 t1.blob2%TYPE := 'blob2';
+ blob3 t1.blob3%TYPE := 'blob3';
+ blob4 t1.blob4%TYPE := 'blob4';
+ yy t1.yy%TYPE := 2001;
+ dd t1.dd%TYPE := '2001-01-01';
+ tm0 t1.tm0%TYPE := '00:00:01';
+ tm3 t1.tm3%TYPE := '00:00:03.333';
+ tm6 t1.tm6%TYPE := '00:00:06.666666';
+ dt0 t1.dt0%TYPE := '2001-01-01 00:00:01';
+ dt3 t1.dt3%TYPE := '2001-01-03 00:00:01.333';
+ dt6 t1.dt6%TYPE := '2001-01-06 00:00:01.666666';
+ ts0 t1.ts0%TYPE := '2002-01-01 00:00:01';
+ ts3 t1.ts3%TYPE := '2002-01-03 00:00:01.333';
+ ts6 t1.ts6%TYPE := '2002-01-06 00:00:01.666666';
+ dc100 t1.dc100%TYPE := 10;
+ dc103 t1.dc103%TYPE := 10.123;
+ dc209 t1.dc209%TYPE := 10.123456789;
+BEGIN
+ CASE
+ WHEN command='create' THEN
+ CREATE TABLE t2 AS SELECT
+ bit6, bit7, bit8,
+ i1,i2,i3,i4,i8,
+ ff,fd, dc100, dc103, dc209,
+ cc,cv,cvu,
+ t1,t2,t3,t4,
+ enum1, set1,
+ blob1, blob2, blob3, blob4,
+ dd, yy,
+ tm0, tm3, tm6,
+ dt0, dt3, dt6,
+ ts0, ts3, ts6;
+ WHEN command='select' THEN
+ SELECT
+ bit6, bit7, bit8,
+ i1,i2,i3,i4,i8,
+ ff,fd, dc100, dc103, dc209,
+ cc,cv,cvu,
+ t1,t2,t3,t4,
+ enum1, set1,
+ blob1, blob2, blob3, blob4,
+ dd, yy,
+ tm0, tm3, tm6,
+ dt0, dt3, dt6,
+ ts0, ts3, ts6;
+ END CASE;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # TABLE
+--echo #
+CALL p1('create');
+SHOW CREATE TABLE t2;
+--vertical_results
+SELECT * FROM t2;
+--horizontal_results
+DROP TABLE t2;
+
+--disable_ps_protocol
+--enable_metadata
+--vertical_results
+CALL p1('select');
+--horizontal_results
+--disable_metadata
+--enable_ps_protocol
+
+--echo #
+--echo # VIEW
+--echo #
+ALTER TABLE t1 RENAME t0;
+CREATE VIEW t1 AS SELECT * FROM t0;
+
+CALL p1('create');
+SHOW CREATE TABLE t2;
+--vertical_results
+SELECT * FROM t2;
+--horizontal_results
+DROP TABLE t2;
+
+--disable_ps_protocol
+--enable_metadata
+--vertical_results
+CALL p1('select');
+--horizontal_results
+--disable_metadata
+--enable_ps_protocol
+
+DROP VIEW t1;
+DROP TABLE t0;
+
+DROP PROCEDURE p1;
+
+--echo #
+--echo # VIEW with subqueries
+--echo #
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,1),(20,2),(30,3),(40,4);
+SELECT AVG(a) FROM t1;
+CREATE VIEW v1 AS SELECT a,1 as b FROM t1 WHERE a>(SELECT AVG(a) FROM t1) AND b>(SELECT 1);
+SELECT * FROM v1;
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a v1.a%TYPE := 10;
+ b v1.b%TYPE := 1;
+BEGIN
+ SELECT a,b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN INT
+AS
+ a v1.a%TYPE := 10;
+ b v1.b%TYPE := 1;
+BEGIN
+ RETURN a+b;
+END;
+$$
+DELIMITER ;$$
+SELECT f1();
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %TYPE variables + INFORMATION_SCHEMA
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ tables_table_name INFORMATION_SCHEMA.TABLES.TABLE_NAME%TYPE;
+ tables_table_rows INFORMATION_SCHEMA.TABLES.TABLE_ROWS%TYPE;
+ processlist_info INFORMATION_SCHEMA.PROCESSLIST.INFO%TYPE;
+ processlist_info_binary INFORMATION_SCHEMA.PROCESSLIST.INFO_BINARY%TYPE;
+BEGIN
+ CREATE TABLE t1 AS SELECT
+ tables_table_name,
+ tables_table_rows,
+ processlist_info,
+ processlist_info_binary;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # %TYPE + Table structure change
+--echo # Data type for both a0 and a1 is chosen in the very beginning
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ a0 t1.a%TYPE;
+BEGIN
+ ALTER TABLE t1 MODIFY a VARCHAR(10); -- This does not affect a1
+ DECLARE
+ a1 t1.a%TYPE;
+ BEGIN
+ CREATE TABLE t2 AS SELECT a0, a1;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END
+$$
+DELIMITER ;$$
+CREATE TABLE t1 (a INT);
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # %TYPE in parameters
+--echo #
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (b SMALLINT);
+DELIMITER $$;
+CREATE PROCEDURE p1(a t1.a%TYPE, b test1.t1.b%TYPE)
+AS
+BEGIN
+ CREATE TABLE t2 AS SELECT a, b;
+END;
+$$
+DELIMITER ;$$
+CALL p1('test', 123);
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE test1.t1;
+DROP DATABASE test1;
+DROP TABLE t1;
+
+--echo #
+--echo # %TYPE in a stored function variables and arguments
+--echo #
+
+CREATE TABLE t1 (a INT);
+SET sql_mode=ORACLE;
+DELIMITER $$;
+CREATE FUNCTION f1 (prm t1.a%TYPE) RETURN INT
+AS
+ a t1.a%TYPE:= prm;
+BEGIN
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+SELECT f1(20);
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # %TYPE in function RETURN clause is not supported yet
+--echo #
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE FUNCTION f1 RETURN t1.a%TYPE
+AS
+BEGIN
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # End of MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+--echo #
+
+
+--echo #
+--echo # MDEV-12089 sql_mode=ORACLE: Understand optional routine name after the END keyword
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1 RETURN INT AS
+BEGIN
+ RETURN 10;
+END f1;
+$$
+DELIMITER ;$$
+DROP FUNCTION f1;
+
+DELIMITER $$;
+CREATE FUNCTION test.f1 RETURN INT AS
+BEGIN
+ RETURN 10;
+END test.f1;
+$$
+DELIMITER ;$$
+DROP FUNCTION f1;
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE FUNCTION test.f1 RETURN INT AS
+BEGIN
+ RETURN 10;
+END test2.f1;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE FUNCTION test.f1 RETURN INT AS
+BEGIN
+ RETURN 10;
+END test.f2;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE FUNCTION f1 RETURN INT AS
+BEGIN
+ RETURN 10;
+END test.f2;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE FUNCTION f1 RETURN INT AS
+BEGIN
+ RETURN 10;
+END test2.f1;
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1 AS
+BEGIN
+ NULL;
+END p1;
+$$
+DELIMITER ;$$
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE test.p1 AS
+BEGIN
+ NULL;
+END test.p1;
+$$
+DELIMITER ;$$
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE PROCEDURE test.p1 AS
+BEGIN
+ NULL;
+END test2.p1;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE PROCEDURE test.p1 AS
+BEGIN
+ NULL;
+END test.p2;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE PROCEDURE p1 AS
+BEGIN
+ NULL;
+END test.p2;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_END_IDENTIFIER_DOES_NOT_MATCH
+CREATE PROCEDURE p1 AS
+BEGIN
+ NULL;
+END test2.p1;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # MDEV-12107 sql_mode=ORACLE: Inside routines the CALL keywoard is optional
+--echo #
+DELIMITER /;
+CREATE OR REPLACE PROCEDURE p1(a INT) AS
+BEGIN
+ SELECT 'This is p1' AS "comment";
+END;
+/
+CREATE OR REPLACE PROCEDURE p2 AS
+BEGIN
+ SELECT 'This is p2' AS "comment";
+END;
+/
+BEGIN
+ p1(10);
+ p2;
+ test.p1(10);
+ test.p2;
+END;
+/
+CREATE PROCEDURE p3 AS
+BEGIN
+ p1(10);
+ p2;
+ test.p1(10);
+ test.p2;
+END
+/
+DELIMITER ;/
+CALL p3;
+DROP PROCEDURE p3;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+SELECT SQL%ROWCOUNT;
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/suite/compat/oracle/t/trigger.test b/mysql-test/suite/compat/oracle/t/trigger.test
new file mode 100644
index 00000000000..45affb2d6e8
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/trigger.test
@@ -0,0 +1,106 @@
+set sql_mode=ORACLE;
+
+--error ER_PARSE_ERROR
+:NEW.a := 1;
+--error ER_PARSE_ERROR
+:OLD.a := 1;
+--error ER_PARSE_ERROR
+:OLa.a := 1;
+
+--error ER_PARSE_ERROR
+SELECT :NEW.a;
+--error ER_PARSE_ERROR
+SELECT :OLD.a;
+--error ER_PARSE_ERROR
+SELECT :OLa.a;
+
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW NEW.a:= 10;
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW :NEW.a:= 10;
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (a INT);
+DELIMITER /;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ IF :NEW.a IS NULL
+ THEN
+ :NEW.a:= 10;
+ END IF;
+END;
+/
+DELIMITER ;/
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT);
+DELIMITER /;
+CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+ IF :OLD.a IS NULL
+ THEN
+ :NEW.a:= 10;
+ END IF;
+END;
+/
+DELIMITER ;/
+INSERT INTO t1 VALUES (NULL);
+UPDATE t1 SET a=NULL;
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+
+CREATE TABLE t1 (a INT, b INT, c INT);
+DELIMITER /;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+DECLARE
+ cnt INT := 0;
+BEGIN
+ IF :NEW.a IS NULL THEN cnt:=cnt+1; END IF;
+ IF :NEW.b IS NULL THEN cnt:=cnt+1; END IF;
+ IF :NEW.c IS NULL THEN :NEW.c:=cnt; END IF;
+END;
+/
+DELIMITER ;/
+INSERT INTO t1 VALUES ();
+INSERT INTO t1 VALUES (1, NULL, NULL);
+INSERT INTO t1 VALUES (NULL, 1, NULL);
+INSERT INTO t1 VALUES (1, 1, NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, total INT);
+DELIMITER $$;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+DECLARE
+ va t1.a%TYPE:= :NEW.a;
+ vb t1.b%TYPE:= :NEW.b;
+BEGIN
+ :NEW.total:= va + vb;
+END;
+$$
+DELIMITER ;$$
+INSERT INTO t1 (a,b) VALUES (10, 20);
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/truncate.test b/mysql-test/suite/compat/oracle/t/truncate.test
new file mode 100644
index 00000000000..ac540047e49
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/truncate.test
@@ -0,0 +1,16 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10588 sql_mode=ORACLE: TRUNCATE TABLE t1 [ {DROP|REUSE} STORAGE ]
+--echo #
+
+CREATE TABLE t1 (a INT);
+TRUNCATE TABLE t1 REUSE STORAGE;
+TRUNCATE TABLE t1 DROP STORAGE;
+DROP TABLE t1;
+
+# REUSE is actually a reserved word in Oracle.
+# But we don't reserve it for MDEV-10588
+
+CREATE TABLE reuse (reuse INT);
+DROP TABLE reuse;
diff --git a/mysql-test/suite/compat/oracle/t/type_blob.test b/mysql-test/suite/compat/oracle/t/type_blob.test
new file mode 100644
index 00000000000..2bfaa77560d
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_blob.test
@@ -0,0 +1,4 @@
+SET sql_mode=ORACLE;
+CREATE TABLE t1 (a BLOB);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/type_clob.test b/mysql-test/suite/compat/oracle/t/type_clob.test
new file mode 100644
index 00000000000..275e368b298
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_clob.test
@@ -0,0 +1,10 @@
+SET sql_mode=ORACLE;
+
+# CLOB is not a reserved word even in sql_mode=ORACLE
+CREATE TABLE clob (clob INT);
+SHOW CREATE TABLE clob;
+DROP TABLE clob;
+
+CREATE TABLE t1 (a CLOB);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/type_date.test b/mysql-test/suite/compat/oracle/t/type_date.test
new file mode 100644
index 00000000000..61f7aa53944
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_date.test
@@ -0,0 +1,4 @@
+SET sql_mode=ORACLE;
+CREATE TABLE t1 (a DATE);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/type_number.test b/mysql-test/suite/compat/oracle/t/type_number.test
new file mode 100644
index 00000000000..d8ea04ab333
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_number.test
@@ -0,0 +1,9 @@
+SET sql_mode=ORACLE;
+
+CREATE TABLE t1 (a NUMBER);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a NUMBER(10,2));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/type_raw.test b/mysql-test/suite/compat/oracle/t/type_raw.test
new file mode 100644
index 00000000000..3b54f5a3735
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_raw.test
@@ -0,0 +1,10 @@
+SET sql_mode=ORACLE;
+
+# RAW is not a reserved word even in sql_mode=ORACLE
+CREATE TABLE raw (raw INT);
+SHOW CREATE TABLE raw;
+DROP TABLE raw;
+
+CREATE TABLE t1 (a RAW(10));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/type_varchar.test b/mysql-test/suite/compat/oracle/t/type_varchar.test
new file mode 100644
index 00000000000..05691bfb8e6
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_varchar.test
@@ -0,0 +1,9 @@
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-11275 sql_mode=ORACLE: CAST(..AS VARCHAR(N))
+--echo #
+
+SELECT CAST(123 AS VARCHAR(10)) FROM DUAL;
+--error ER_PARSE_ERROR
+SELECT CAST(123 AS VARCHAR) FROM DUAL;
diff --git a/mysql-test/suite/compat/oracle/t/type_varchar2.test b/mysql-test/suite/compat/oracle/t/type_varchar2.test
new file mode 100644
index 00000000000..bd0243713b6
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/type_varchar2.test
@@ -0,0 +1,19 @@
+SET sql_mode=ORACLE;
+
+# VARCHAR2 is not a reserved word even in sql_mode=ORACLE
+CREATE TABLE varchar2 (varchar2 INT);
+SHOW CREATE TABLE varchar2;
+DROP TABLE varchar2;
+
+CREATE TABLE t1 (a VARCHAR2(10));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-11275 sql_mode=ORACLE: CAST(..AS VARCHAR(N))
+--echo #
+
+SELECT CAST(123 AS VARCHAR2(10)) FROM DUAL;
+--error ER_PARSE_ERROR
+SELECT CAST(123 AS VARCHAR2) FROM DUAL;
diff --git a/mysql-test/suite/compat/oracle/t/variables.test b/mysql-test/suite/compat/oracle/t/variables.test
new file mode 100644
index 00000000000..4705cac11c0
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/variables.test
@@ -0,0 +1,38 @@
+SET sql_mode=oracle;
+
+--echo #
+--echo # MDEV-10411 Providing compatibility for basic PL/SQL constructs
+--echo # Part 6: Assignment operator
+--echo #
+
+max_sort_length:=1030;
+SELECT @@max_sort_length;
+max_sort_length:=DEFAULT;
+
+--echo #
+--echo # Testing that SP variables shadow global variables in assignments
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+BEGIN
+ max_sort_length:=1030;
+ DECLARE
+ max_sort_length INT DEFAULT 1031;
+ BEGIN
+ SELECT @@max_sort_length, max_sort_length;
+ max_sort_length:=1032;
+ SELECT @@max_sort_length, max_sort_length;
+ END;
+ SELECT @@max_sort_length;
+ max_sort_length:= DEFAULT;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # End of MDEV-10411 Providing compatibility for basic PL/SQL constructs (part 6)
+--echo #
diff --git a/mysql-test/suite/engines/iuds/r/insert_number.result b/mysql-test/suite/engines/iuds/r/insert_number.result
index 6119e624e8c..b70c39341ad 100644
--- a/mysql-test/suite/engines/iuds/r/insert_number.result
+++ b/mysql-test/suite/engines/iuds/r/insert_number.result
@@ -34224,12 +34224,8 @@ c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 1 2 3 4 5
-0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7 LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 1 2 3 4 5
-0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t3 WHERE c2 >= -9223372036854775809 AND c2 < 9223372036854775808 AND c7 = 35 ORDER BY c2,c7;
c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
@@ -34391,12 +34387,8 @@ c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7 DESC;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 31 32 33 34 35
-0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7 DESC LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 31 32 33 34 35
-0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t3 WHERE c2 >= -9223372036854775809 AND c2 < 9223372036854775808 AND c7 = 35 ORDER BY c2,c7 DESC;
c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
@@ -34651,12 +34643,8 @@ c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 1 2 3 4 5
-0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7 LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 1 2 3 4 5
-0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t3 WHERE c2 >= -9223372036854775809 AND c2 < 9223372036854775808 AND c7 = 35 ORDER BY c2,c7;
c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
@@ -34818,12 +34806,8 @@ c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7 DESC;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 31 32 33 34 35
-0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t3 WHERE c2 IN (-9223372036854775809,9223372036854775808) ORDER BY c2,c7 DESC LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
-0 -9223372036854775808 31 32 33 34 35
-0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t3 WHERE c2 >= -9223372036854775809 AND c2 < 9223372036854775808 AND c7 = 35 ORDER BY c2,c7 DESC;
c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result
index 04e689cc651..481787e4eaa 100644
--- a/mysql-test/suite/funcs_1/r/innodb_func_view.result
+++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result
@@ -857,7 +857,7 @@ my_varbinary_1000, id FROM t1_values
WHERE select_id = 155 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_varbinary_1000`) AS `LENGTH(my_varbinary_1000)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_varbinary_1000`) AS `LENGTH(my_varbinary_1000)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 155 OR select_id IS NULL) order by id;
@@ -871,7 +871,7 @@ my_binary_30, id FROM t1_values
WHERE select_id = 154 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_binary_30`) AS `LENGTH(my_binary_30)`,`t1_values`.`my_binary_30` AS `my_binary_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_binary_30`) AS `LENGTH(my_binary_30)`,`t1_values`.`my_binary_30` AS `my_binary_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 154 OR select_id IS NULL) order by id;
@@ -885,7 +885,7 @@ my_varchar_1000, id FROM t1_values
WHERE select_id = 153 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_varchar_1000`) AS `LENGTH(my_varchar_1000)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_varchar_1000`) AS `LENGTH(my_varchar_1000)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 153 OR select_id IS NULL) order by id;
@@ -899,7 +899,7 @@ my_char_30, id FROM t1_values
WHERE select_id = 152 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_char_30`) AS `LENGTH(my_char_30)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_char_30`) AS `LENGTH(my_char_30)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 152 OR select_id IS NULL) order by id;
diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_0102.result b/mysql-test/suite/funcs_1/r/innodb_trig_0102.result
index 77fabeaef77..2bc3f46821d 100644
--- a/mysql-test/suite/funcs_1/r/innodb_trig_0102.result
+++ b/mysql-test/suite/funcs_1/r/innodb_trig_0102.result
@@ -253,7 +253,7 @@ Testcase 3.5.1.10:
------------------
CREATE TRIGGER trg7_1 BEFORE UPDATE on tb3 for each row set new.f120 ='X';
CREATE TRIGGER trg7_1 AFTER INSERT on tb3 for each row set @x ='Y';
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg7_1' already exists
drop trigger trg7_1;
Testcase 3.5.1.?:
@@ -266,7 +266,7 @@ create trigger trig before insert on t1
for each row set new.f1 ='trig t1';
create trigger trig before update on t2
for each row set new.f1 ='trig t2';
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trig' already exists
insert into t1 value ('insert to t1',1);
select * from t1;
f1 f2
diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result
index 81ead0c9346..4753efd1794 100644
--- a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result
+++ b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result
@@ -245,7 +245,7 @@ Testcase 3.5.5.3:
Create view vw3 as select f118 from tb3;
Create trigger trg3 before INSERT
on vw3 for each row set new.f118='s';
-ERROR HY000: 'test.vw3' is not BASE TABLE
+ERROR HY000: 'test.vw3' is not of type 'BASE TABLE'
drop view vw3;
Testcase 3.5.5.4:
@@ -459,7 +459,7 @@ Create trigger trg_3_406010_2 AFTER DELETE
on tb3 for each row set @test_var=@test_var+50;
Create trigger trg_3_406010_1 AFTER INSERT
on tb3 for each row set @test_var=@test_var+1;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg_3_406010_1' already exists
select @test_var;
@test_var
1
diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result
index 0ce0130e727..d81d09353e1 100644
--- a/mysql-test/suite/funcs_1/r/innodb_views.result
+++ b/mysql-test/suite/funcs_1/r/innodb_views.result
@@ -3520,12 +3520,12 @@ f1
DROP TRIGGER tr1 ;
SET @a:=0 ;
CREATE TRIGGER tr1 BEFORE INSERT ON v1 FOR EACH ROW SET @a:=1 ;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
RENAME TABLE v1 TO v2;
RENAME VIEW v2 TO v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'VIEW v2 TO v1' at line 1
ALTER TABLE v2 RENAME AS v1;
-ERROR HY000: 'test.v2' is not BASE TABLE
+ERROR HY000: 'test.v2' is not of type 'BASE TABLE'
ALTER VIEW v1 RENAME AS v2;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RENAME AS v2' at line 1
DROP TABLE IF EXISTS t1, t2 ;
@@ -3535,12 +3535,12 @@ CREATE TABLE t1 ( f1 DATE, f2 BLOB, f3 DOUBLE );
CREATE VIEW v1 AS SELECT f1, f2, f3 FROM t1;
ALTER TABLE t1 ADD PRIMARY KEY(f1);
ALTER TABLE v1 ADD PRIMARY KEY(f1);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
ALTER VIEW v1 ADD PRIMARY KEY(f1);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ADD PRIMARY KEY(f1)' at line 1
CREATE INDEX t1_idx ON t1(f3);
CREATE INDEX v1_idx ON v1(f3);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
DROP TABLE t1;
DROP VIEW v1;
@@ -4085,9 +4085,9 @@ Drop view test.v1 ;
Testcase 3.3.1.14
--------------------------------------------------------------------------------
CREATE OR REPLACE VIEW test.tb2 AS SELECT * From tb2 LIMIT 2;
-ERROR HY000: 'test.tb2' is not VIEW
+ERROR HY000: 'test.tb2' is not of type 'VIEW'
CREATE OR REPLACE VIEW tb2 AS SELECT * From tb2 LIMIT 2;
-ERROR HY000: 'test.tb2' is not VIEW
+ERROR HY000: 'test.tb2' is not of type 'VIEW'
Testcase 3.3.1.15
--------------------------------------------------------------------------------
@@ -4314,7 +4314,7 @@ CREATE VIEW v2 AS Select * from test.v1;
ERROR 42S02: Table 'test.v1' doesn't exist
DROP VIEW IF EXISTS v2;
Warnings:
-Note 1051 Unknown table 'test.v2'
+Note 4068 Unknown VIEW: 'test.v2'
Testcase 3.3.1.25
--------------------------------------------------------------------------------
@@ -7566,7 +7566,7 @@ Call sp1() ;
ERROR 42000: PROCEDURE test.sp1 does not exist
Drop view if exists test.v1 ;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
Drop procedure sp1 ;
ERROR 42000: PROCEDURE test.sp1 does not exist
@@ -21307,12 +21307,12 @@ CREATE TABLE t1 ( f1 VARCHAR(1000) ) ENGINE = innodb ;
CREATE VIEW v1 AS SELECT f1 FROM t1;
DROP VIEW v1;
DROP VIEW v1;
-ERROR 42S02: Unknown table 'test.v1'
+ERROR 42S02: Unknown VIEW: 'test.v1'
CREATE VIEW v1 AS SELECT f1 FROM t1;
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
Testcase 3.3.1.68
--------------------------------------------------------------------------------
@@ -21324,31 +21324,31 @@ CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top CASCADE ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base CASCADE ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top RESTRICT ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base RESTRICT ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
Testcase 3.3.1.69, 3.3.1.70, 3.3.1.A5
diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result
index 765869a312d..3a75e4abac5 100644
--- a/mysql-test/suite/funcs_1/r/memory_func_view.result
+++ b/mysql-test/suite/funcs_1/r/memory_func_view.result
@@ -858,7 +858,7 @@ my_varbinary_1000, id FROM t1_values
WHERE select_id = 155 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_varbinary_1000`) AS `LENGTH(my_varbinary_1000)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_varbinary_1000`) AS `LENGTH(my_varbinary_1000)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 155 OR select_id IS NULL) order by id;
@@ -872,7 +872,7 @@ my_binary_30, id FROM t1_values
WHERE select_id = 154 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_binary_30`) AS `LENGTH(my_binary_30)`,`t1_values`.`my_binary_30` AS `my_binary_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_binary_30`) AS `LENGTH(my_binary_30)`,`t1_values`.`my_binary_30` AS `my_binary_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 154 OR select_id IS NULL) order by id;
@@ -886,7 +886,7 @@ my_varchar_1000, id FROM t1_values
WHERE select_id = 153 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_varchar_1000`) AS `LENGTH(my_varchar_1000)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_varchar_1000`) AS `LENGTH(my_varchar_1000)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 153 OR select_id IS NULL) order by id;
@@ -900,7 +900,7 @@ my_char_30, id FROM t1_values
WHERE select_id = 152 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_char_30`) AS `LENGTH(my_char_30)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_char_30`) AS `LENGTH(my_char_30)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 152 OR select_id IS NULL) order by id;
diff --git a/mysql-test/suite/funcs_1/r/memory_trig_0102.result b/mysql-test/suite/funcs_1/r/memory_trig_0102.result
index 85da4aa7832..fa35ef6e7ae 100644
--- a/mysql-test/suite/funcs_1/r/memory_trig_0102.result
+++ b/mysql-test/suite/funcs_1/r/memory_trig_0102.result
@@ -254,7 +254,7 @@ Testcase 3.5.1.10:
------------------
CREATE TRIGGER trg7_1 BEFORE UPDATE on tb3 for each row set new.f120 ='X';
CREATE TRIGGER trg7_1 AFTER INSERT on tb3 for each row set @x ='Y';
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg7_1' already exists
drop trigger trg7_1;
Testcase 3.5.1.?:
@@ -267,7 +267,7 @@ create trigger trig before insert on t1
for each row set new.f1 ='trig t1';
create trigger trig before update on t2
for each row set new.f1 ='trig t2';
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trig' already exists
insert into t1 value ('insert to t1',1);
select * from t1;
f1 f2
diff --git a/mysql-test/suite/funcs_1/r/memory_trig_0407.result b/mysql-test/suite/funcs_1/r/memory_trig_0407.result
index 72a7cb4f01d..c21c206f118 100644
--- a/mysql-test/suite/funcs_1/r/memory_trig_0407.result
+++ b/mysql-test/suite/funcs_1/r/memory_trig_0407.result
@@ -245,7 +245,7 @@ Testcase 3.5.5.3:
Create view vw3 as select f118 from tb3;
Create trigger trg3 before INSERT
on vw3 for each row set new.f118='s';
-ERROR HY000: 'test.vw3' is not BASE TABLE
+ERROR HY000: 'test.vw3' is not of type 'BASE TABLE'
drop view vw3;
Testcase 3.5.5.4:
@@ -459,7 +459,7 @@ Create trigger trg_3_406010_2 AFTER DELETE
on tb3 for each row set @test_var=@test_var+50;
Create trigger trg_3_406010_1 AFTER INSERT
on tb3 for each row set @test_var=@test_var+1;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg_3_406010_1' already exists
select @test_var;
@test_var
1
diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result
index 0ca6e8d94d8..ca24c73d933 100644
--- a/mysql-test/suite/funcs_1/r/memory_views.result
+++ b/mysql-test/suite/funcs_1/r/memory_views.result
@@ -3521,12 +3521,12 @@ f1
DROP TRIGGER tr1 ;
SET @a:=0 ;
CREATE TRIGGER tr1 BEFORE INSERT ON v1 FOR EACH ROW SET @a:=1 ;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
RENAME TABLE v1 TO v2;
RENAME VIEW v2 TO v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'VIEW v2 TO v1' at line 1
ALTER TABLE v2 RENAME AS v1;
-ERROR HY000: 'test.v2' is not BASE TABLE
+ERROR HY000: 'test.v2' is not of type 'BASE TABLE'
ALTER VIEW v1 RENAME AS v2;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RENAME AS v2' at line 1
DROP TABLE IF EXISTS t1, t2 ;
@@ -3536,12 +3536,12 @@ CREATE TABLE t1 ( f1 DATE, f2 BLOB, f3 DOUBLE );
CREATE VIEW v1 AS SELECT f1, f2, f3 FROM t1;
ALTER TABLE t1 ADD PRIMARY KEY(f1);
ALTER TABLE v1 ADD PRIMARY KEY(f1);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
ALTER VIEW v1 ADD PRIMARY KEY(f1);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ADD PRIMARY KEY(f1)' at line 1
CREATE INDEX t1_idx ON t1(f3);
CREATE INDEX v1_idx ON v1(f3);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
DROP TABLE t1;
DROP VIEW v1;
@@ -4086,9 +4086,9 @@ Drop view test.v1 ;
Testcase 3.3.1.14
--------------------------------------------------------------------------------
CREATE OR REPLACE VIEW test.tb2 AS SELECT * From tb2 LIMIT 2;
-ERROR HY000: 'test.tb2' is not VIEW
+ERROR HY000: 'test.tb2' is not of type 'VIEW'
CREATE OR REPLACE VIEW tb2 AS SELECT * From tb2 LIMIT 2;
-ERROR HY000: 'test.tb2' is not VIEW
+ERROR HY000: 'test.tb2' is not of type 'VIEW'
Testcase 3.3.1.15
--------------------------------------------------------------------------------
@@ -4315,7 +4315,7 @@ CREATE VIEW v2 AS Select * from test.v1;
ERROR 42S02: Table 'test.v1' doesn't exist
DROP VIEW IF EXISTS v2;
Warnings:
-Note 1051 Unknown table 'test.v2'
+Note 4068 Unknown VIEW: 'test.v2'
Testcase 3.3.1.25
--------------------------------------------------------------------------------
@@ -7567,7 +7567,7 @@ Call sp1() ;
ERROR 42000: PROCEDURE test.sp1 does not exist
Drop view if exists test.v1 ;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
Drop procedure sp1 ;
ERROR 42000: PROCEDURE test.sp1 does not exist
@@ -21309,12 +21309,12 @@ CREATE TABLE t1 ( f1 VARCHAR(1000) ) ENGINE = memory ;
CREATE VIEW v1 AS SELECT f1 FROM t1;
DROP VIEW v1;
DROP VIEW v1;
-ERROR 42S02: Unknown table 'test.v1'
+ERROR 42S02: Unknown VIEW: 'test.v1'
CREATE VIEW v1 AS SELECT f1 FROM t1;
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
Testcase 3.3.1.68
--------------------------------------------------------------------------------
@@ -21326,31 +21326,31 @@ CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top CASCADE ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base CASCADE ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top RESTRICT ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base RESTRICT ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
Testcase 3.3.1.69, 3.3.1.70, 3.3.1.A5
diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result
index 765869a312d..3a75e4abac5 100644
--- a/mysql-test/suite/funcs_1/r/myisam_func_view.result
+++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result
@@ -858,7 +858,7 @@ my_varbinary_1000, id FROM t1_values
WHERE select_id = 155 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_varbinary_1000`) AS `LENGTH(my_varbinary_1000)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_varbinary_1000`) AS `LENGTH(my_varbinary_1000)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 155 OR select_id IS NULL) order by id;
@@ -872,7 +872,7 @@ my_binary_30, id FROM t1_values
WHERE select_id = 154 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_binary_30`) AS `LENGTH(my_binary_30)`,`t1_values`.`my_binary_30` AS `my_binary_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_binary_30`) AS `LENGTH(my_binary_30)`,`t1_values`.`my_binary_30` AS `my_binary_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 154 OR select_id IS NULL) order by id;
@@ -886,7 +886,7 @@ my_varchar_1000, id FROM t1_values
WHERE select_id = 153 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_varchar_1000`) AS `LENGTH(my_varchar_1000)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_varchar_1000`) AS `LENGTH(my_varchar_1000)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 153 OR select_id IS NULL) order by id;
@@ -900,7 +900,7 @@ my_char_30, id FROM t1_values
WHERE select_id = 152 OR select_id IS NULL order by id;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select length(`t1_values`.`my_char_30`) AS `LENGTH(my_char_30)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select octet_length(`t1_values`.`my_char_30`) AS `LENGTH(my_char_30)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
SELECT v1.* FROM v1
WHERE v1.id IN (SELECT id FROM t1_values
WHERE select_id = 152 OR select_id IS NULL) order by id;
diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_0102.result b/mysql-test/suite/funcs_1/r/myisam_trig_0102.result
index 85da4aa7832..fa35ef6e7ae 100644
--- a/mysql-test/suite/funcs_1/r/myisam_trig_0102.result
+++ b/mysql-test/suite/funcs_1/r/myisam_trig_0102.result
@@ -254,7 +254,7 @@ Testcase 3.5.1.10:
------------------
CREATE TRIGGER trg7_1 BEFORE UPDATE on tb3 for each row set new.f120 ='X';
CREATE TRIGGER trg7_1 AFTER INSERT on tb3 for each row set @x ='Y';
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg7_1' already exists
drop trigger trg7_1;
Testcase 3.5.1.?:
@@ -267,7 +267,7 @@ create trigger trig before insert on t1
for each row set new.f1 ='trig t1';
create trigger trig before update on t2
for each row set new.f1 ='trig t2';
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trig' already exists
insert into t1 value ('insert to t1',1);
select * from t1;
f1 f2
diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result
index 72a7cb4f01d..c21c206f118 100644
--- a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result
+++ b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result
@@ -245,7 +245,7 @@ Testcase 3.5.5.3:
Create view vw3 as select f118 from tb3;
Create trigger trg3 before INSERT
on vw3 for each row set new.f118='s';
-ERROR HY000: 'test.vw3' is not BASE TABLE
+ERROR HY000: 'test.vw3' is not of type 'BASE TABLE'
drop view vw3;
Testcase 3.5.5.4:
@@ -459,7 +459,7 @@ Create trigger trg_3_406010_2 AFTER DELETE
on tb3 for each row set @test_var=@test_var+50;
Create trigger trg_3_406010_1 AFTER INSERT
on tb3 for each row set @test_var=@test_var+1;
-ERROR HY000: Trigger already exists
+ERROR HY000: Trigger 'test.trg_3_406010_1' already exists
select @test_var;
@test_var
1
diff --git a/mysql-test/suite/funcs_1/r/myisam_views-big.result b/mysql-test/suite/funcs_1/r/myisam_views-big.result
index b6537582055..feb67539cb9 100644
--- a/mysql-test/suite/funcs_1/r/myisam_views-big.result
+++ b/mysql-test/suite/funcs_1/r/myisam_views-big.result
@@ -4023,12 +4023,12 @@ f1
DROP TRIGGER tr1 ;
SET @a:=0 ;
CREATE TRIGGER tr1 BEFORE INSERT ON v1 FOR EACH ROW SET @a:=1 ;
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
RENAME TABLE v1 TO v2;
RENAME VIEW v2 TO v1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'VIEW v2 TO v1' at line 1
ALTER TABLE v2 RENAME AS v1;
-ERROR HY000: 'test.v2' is not BASE TABLE
+ERROR HY000: 'test.v2' is not of type 'BASE TABLE'
ALTER VIEW v1 RENAME AS v2;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RENAME AS v2' at line 1
DROP TABLE IF EXISTS t1, t2 ;
@@ -4038,12 +4038,12 @@ CREATE TABLE t1 ( f1 DATE, f2 BLOB, f3 DOUBLE );
CREATE VIEW v1 AS SELECT f1, f2, f3 FROM t1;
ALTER TABLE t1 ADD PRIMARY KEY(f1);
ALTER TABLE v1 ADD PRIMARY KEY(f1);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
ALTER VIEW v1 ADD PRIMARY KEY(f1);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ADD PRIMARY KEY(f1)' at line 1
CREATE INDEX t1_idx ON t1(f3);
CREATE INDEX v1_idx ON v1(f3);
-ERROR HY000: 'test.v1' is not BASE TABLE
+ERROR HY000: 'test.v1' is not of type 'BASE TABLE'
DROP TABLE t1;
DROP VIEW v1;
@@ -4604,9 +4604,9 @@ Drop view test.v1 ;
Testcase 3.3.1.14
--------------------------------------------------------------------------------
CREATE OR REPLACE VIEW test.tb2 AS SELECT * From tb2 LIMIT 2;
-ERROR HY000: 'test.tb2' is not VIEW
+ERROR HY000: 'test.tb2' is not of type 'VIEW'
CREATE OR REPLACE VIEW tb2 AS SELECT * From tb2 LIMIT 2;
-ERROR HY000: 'test.tb2' is not VIEW
+ERROR HY000: 'test.tb2' is not of type 'VIEW'
Testcase 3.3.1.15
--------------------------------------------------------------------------------
@@ -4784,7 +4784,7 @@ CREATE VIEW v2 AS Select * from test.v1;
ERROR 42S02: Table 'test.v1' doesn't exist
DROP VIEW IF EXISTS v2;
Warnings:
-Note 1051 Unknown table 'test.v2'
+Note 4068 Unknown VIEW: 'test.v2'
Testcase 3.3.1.25
--------------------------------------------------------------------------------
@@ -8387,7 +8387,7 @@ Call sp1() ;
ERROR 42000: PROCEDURE test.sp1 does not exist
Drop view if exists test.v1 ;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
Drop procedure sp1 ;
ERROR 42000: PROCEDURE test.sp1 does not exist
@@ -22984,12 +22984,12 @@ CREATE TABLE t1 ( f1 VARCHAR(1000) ) ENGINE = myisam ;
CREATE VIEW v1 AS SELECT f1 FROM t1;
DROP VIEW v1;
DROP VIEW v1;
-ERROR 42S02: Unknown table 'test.v1'
+ERROR 42S02: Unknown VIEW: 'test.v1'
CREATE VIEW v1 AS SELECT f1 FROM t1;
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v1;
Warnings:
-Note 1051 Unknown table 'test.v1'
+Note 4068 Unknown VIEW: 'test.v1'
Testcase 3.3.1.68
--------------------------------------------------------------------------------
@@ -23001,31 +23001,31 @@ CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top CASCADE ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base CASCADE ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
CREATE VIEW v1_base AS SELECT * FROM t1;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_top RESTRICT ;
DROP VIEW v1_top;
-ERROR 42S02: Unknown table 'test.v1_top'
+ERROR 42S02: Unknown VIEW: 'test.v1_top'
CREATE VIEW v1_top AS SELECT * FROM v1_base;
DROP VIEW v1_base RESTRICT ;
DROP VIEW v1_base;
-ERROR 42S02: Unknown table 'test.v1_base'
+ERROR 42S02: Unknown VIEW: 'test.v1_base'
DROP VIEW v1_top;
Testcase 3.3.1.69, 3.3.1.70, 3.3.1.A5
diff --git a/mysql-test/suite/funcs_1/views/views_master.inc b/mysql-test/suite/funcs_1/views/views_master.inc
index 54e7f2af54b..17f5c1e5529 100644
--- a/mysql-test/suite/funcs_1/views/views_master.inc
+++ b/mysql-test/suite/funcs_1/views/views_master.inc
@@ -2745,7 +2745,7 @@ CREATE VIEW v1 AS SELECT f1 FROM t1;
# DROP VIEW
DROP VIEW v1;
---error ER_BAD_TABLE_ERROR
+--error ER_UNKNOWN_VIEW
DROP VIEW v1;
CREATE VIEW v1 AS SELECT f1 FROM t1;
@@ -2792,7 +2792,7 @@ while ($num1)
# DROP VIEW v1_top < |RESTRICD|CASCADE> must be successful.
eval $aux1 ;
# Check, that v1_top really no more exists + cleanup for the second sub test
- --error ER_BAD_TABLE_ERROR
+ --error ER_UNKNOWN_VIEW
DROP VIEW v1_top;
CREATE VIEW v1_top AS SELECT * FROM v1_base;
diff --git a/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_innodb.result b/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_innodb.result
index f8f447d493d..5e165b42be7 100644
--- a/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_innodb.result
@@ -915,7 +915,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
`b` varchar(10) DEFAULT NULL,
- `c` varchar(20) GENERATED ALWAYS AS (insert(`a`,length(`a`),length(`b`),`b`)) VIRTUAL
+ `c` varchar(20) GENERATED ALWAYS AS (insert(`a`,octet_length(`a`),octet_length(`b`),`b`)) VIRTUAL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values ('start,','end',default);
select * from t1;
@@ -978,7 +978,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) GENERATED ALWAYS AS (length(`a`)) VIRTUAL
+ `b` int(11) GENERATED ALWAYS AS (octet_length(`a`)) VIRTUAL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values ('text',default);
select * from t1;
@@ -1142,7 +1142,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) GENERATED ALWAYS AS (length(`a`)) VIRTUAL
+ `b` int(11) GENERATED ALWAYS AS (octet_length(`a`)) VIRTUAL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values ('text',default);
select * from t1;
diff --git a/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_myisam.result b/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_myisam.result
index 9db5f0c7c38..7a18bf2d8fb 100644
--- a/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_myisam.result
+++ b/mysql-test/suite/gcol/r/gcol_supported_sql_funcs_myisam.result
@@ -915,7 +915,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
`b` varchar(10) DEFAULT NULL,
- `c` varchar(20) GENERATED ALWAYS AS (insert(`a`,length(`a`),length(`b`),`b`)) VIRTUAL
+ `c` varchar(20) GENERATED ALWAYS AS (insert(`a`,octet_length(`a`),octet_length(`b`),`b`)) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ('start,','end',default);
select * from t1;
@@ -978,7 +978,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) GENERATED ALWAYS AS (length(`a`)) VIRTUAL
+ `b` int(11) GENERATED ALWAYS AS (octet_length(`a`)) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ('text',default);
select * from t1;
@@ -1142,7 +1142,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) GENERATED ALWAYS AS (length(`a`)) VIRTUAL
+ `b` int(11) GENERATED ALWAYS AS (octet_length(`a`)) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ('text',default);
select * from t1;
diff --git a/mysql-test/suite/innodb/r/innodb_gis.result b/mysql-test/suite/innodb/r/innodb_gis.result
index 35ea5104acb..a99d7dd72a5 100644
--- a/mysql-test/suite/innodb/r/innodb_gis.result
+++ b/mysql-test/suite/innodb/r/innodb_gis.result
@@ -507,8 +507,8 @@ down3,left3,right3,up3
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
equals
center
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-intersect
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+intersects
big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
overlaps
diff --git a/mysql-test/suite/innodb/r/table_flags.result b/mysql-test/suite/innodb/r/table_flags.result
index 5cf163ba4ae..ac7187cd610 100644
--- a/mysql-test/suite/innodb/r/table_flags.result
+++ b/mysql-test/suite/innodb/r/table_flags.result
@@ -119,10 +119,20 @@ ERROR 42S02: Table 'test.tc' doesn't exist in engine
SHOW CREATE TABLE td;
ERROR 42S02: Table 'test.td' doesn't exist in engine
SHOW CREATE TABLE tz;
-ERROR 42S02: Table 'test.tz' doesn't exist in engine
+Table Create Table
+tz CREATE TABLE `tz` (
+ `a` int(11) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1
+BEGIN;
+INSERT INTO tz VALUES(42);
+ROLLBACK;
+SELECT * FROM tz;
+a
+42
SHOW CREATE TABLE tp;
ERROR 42S02: Table 'test.tp' doesn't exist in engine
-FOUND 6 /InnoDB: Table `test`.`t[czp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err
+FOUND 4 /InnoDB: Table `test`.`t[cp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err
FOUND 2 /InnoDB: Refusing to load '\..test.td\.ibd' \(id=3, flags=0x1?[2ae]1\); dictionary contains id=3, flags=0x10[01][2ae]1\b/ in mysqld.1.err
FOUND 2 /InnoDB: Table `test`\.`tr` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b/ in mysqld.1.err
Restoring SYS_TABLES clustered index root page (8)
@@ -160,7 +170,6 @@ BEGIN;
INSERT INTO tr VALUES(1);
INSERT INTO tc VALUES(1);
INSERT INTO td VALUES(1);
-INSERT INTO tz VALUES(1);
INSERT INTO tp VALUES(1);
ROLLBACK;
SELECT * FROM tr;
@@ -169,8 +178,6 @@ SELECT * FROM tc;
a
SELECT * FROM td;
a
-SELECT * FROM tz;
-a
SELECT * FROM tp;
a
DROP TABLE tr,tc,td,tz,tp;
diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test
index d3dafa22318..a2dd249f090 100644
--- a/mysql-test/suite/innodb/t/table_flags.test
+++ b/mysql-test/suite/innodb/t/table_flags.test
@@ -5,7 +5,7 @@
--disable_query_log
call mtr.add_suppression("InnoDB: Table `mysql`\\.`innodb_table_stats` not found");
call mtr.add_suppression("InnoDB: incorrect flags in SYS_TABLES");
-call mtr.add_suppression("InnoDB: Table `test`.`t[czp]` in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=(129|289|3873|1232[31]) SYS_TABLES\\.N_COLS=2147483649\\r?$");
+call mtr.add_suppression("InnoDB: Table `test`.`t[cp]` in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=(129|289|3873|1232[31]) SYS_TABLES\\.N_COLS=2147483649\\r?$");
call mtr.add_suppression("InnoDB: Table `test`\\.`tr` in InnoDB data dictionary contains invalid flags\\. SYS_TABLES\\.TYPE=65 SYS_TABLES\\.MIX_LEN=4294967295\\r?$");
call mtr.add_suppression("InnoDB: Refusing to load '\\..test.td\\.ibd' \\(id=3, flags=0x([2e]1)\\); dictionary contains id=3, flags=0x100\\1\\r?$");
call mtr.add_suppression("InnoDB: Refusing to load '\\..test.td\\.ibd' \\(id=3, flags=0x(1[2ae]1)\\); dictionary contains id=3, flags=0x10\\1\\r?$");
@@ -134,15 +134,19 @@ SHOW CREATE TABLE tr;
SHOW CREATE TABLE tc;
--error ER_NO_SUCH_TABLE_IN_ENGINE
SHOW CREATE TABLE td;
---error ER_NO_SUCH_TABLE_IN_ENGINE
+# This table was converted to NO_ROLLBACK due to the SYS_TABLES.TYPE change.
SHOW CREATE TABLE tz;
+BEGIN;
+INSERT INTO tz VALUES(42);
+ROLLBACK;
+SELECT * FROM tz;
--error ER_NO_SUCH_TABLE_IN_ENGINE
SHOW CREATE TABLE tp;
--source include/shutdown_mysqld.inc
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
---let SEARCH_PATTERN= InnoDB: Table `test`.`t[czp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649
+--let SEARCH_PATTERN= InnoDB: Table `test`.`t[cp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649
--source include/search_pattern_in_file.inc
--let SEARCH_PATTERN= InnoDB: Refusing to load '\..test.td\.ibd' \(id=3, flags=0x1?[2ae]1\); dictionary contains id=3, flags=0x10[01][2ae]1\b
--source include/search_pattern_in_file.inc
@@ -179,14 +183,17 @@ BEGIN;
INSERT INTO tr VALUES(1);
INSERT INTO tc VALUES(1);
INSERT INTO td VALUES(1);
-INSERT INTO tz VALUES(1);
+# We cannot access tz, because due to our fiddling of the NO_ROLLBACK flag,
+# it now has a record with DB_TRX_ID=0, which is invalid for
+# transactional tables until MDEV-12288 is implemented.
+# INSERT INTO tz VALUES(1);
INSERT INTO tp VALUES(1);
ROLLBACK;
SELECT * FROM tr;
SELECT * FROM tc;
SELECT * FROM td;
-SELECT * FROM tz;
+# SELECT * FROM tz;
SELECT * FROM tp;
DROP TABLE tr,tc,td,tz,tp;
diff --git a/mysql-test/suite/innodb_fts/r/fulltext_misc.result b/mysql-test/suite/innodb_fts/r/fulltext_misc.result
index 6a24d9aea58..f3e1ef519fd 100644
--- a/mysql-test/suite/innodb_fts/r/fulltext_misc.result
+++ b/mysql-test/suite/innodb_fts/r/fulltext_misc.result
@@ -148,7 +148,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t1 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by `a` + 12
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by `a` + 12
# Should not crash
SELECT * FROM t1 UNION SELECT * FROM t1 ORDER BY a + 12;
a
@@ -163,7 +163,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 UNION t1 ALL NULL NULL NULL NULL 2 100.00
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (match `a` against ('+abc' in boolean mode))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by (match `a` against ('+abc' in boolean mode))
# Should not crash
SELECT * FROM t1 UNION SELECT * FROM t1
ORDER BY MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE);
@@ -181,7 +181,7 @@ NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #-1
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` union select `test`.`t1`.`a` AS `a` from `test`.`t1` order by <expr_cache><`a`>((select `a` from `test`.`t2` where `test`.`t2`.`b` = 12))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` union /* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` order by <expr_cache><`a`>((/* select#3 */ select `a` from `test`.`t2` where `test`.`t2`.`b` = 12))
# Should not crash
SELECT * FROM t1 UNION SELECT * FROM t1
ORDER BY (SELECT a FROM t2 WHERE b = 12);
diff --git a/mysql-test/suite/innodb_gis/r/0.result b/mysql-test/suite/innodb_gis/r/0.result
index 90657acaefc..e5b285e519a 100644
--- a/mysql-test/suite/innodb_gis/r/0.result
+++ b/mysql-test/suite/innodb_gis/r/0.result
@@ -507,8 +507,8 @@ down3,left3,right3,up3
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
equals
center
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-intersect
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+intersects
big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
overlaps
diff --git a/mysql-test/suite/innodb_gis/r/1.result b/mysql-test/suite/innodb_gis/r/1.result
index 094ec0185f8..0c0c6834acf 100644
--- a/mysql-test/suite/innodb_gis/r/1.result
+++ b/mysql-test/suite/innodb_gis/r/1.result
@@ -681,7 +681,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g
select ST_asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def ST_asbinary(g) 252 4294967295 0 Y 128 0 63
+def ST_asbinary(g) 251 4294967295 0 Y 128 0 63
ST_asbinary(g)
drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, INDEX(b(5)));
@@ -868,8 +868,8 @@ down3,left3,right3,up3
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRequals FROM t1 a1 JOIN t1 a2 ON MBREquals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
MBRequals
center
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-intersect
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+intersects
big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRoverlaps FROM t1 a1 JOIN t1 a2 ON MBROverlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
MBRoverlaps
@@ -996,9 +996,7 @@ ST_GEOMFROMTEXT(
'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))'));
# must not crash
SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
-1
-Warnings:
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x06\x00\x00\x00\x01\x00\x00\x00\x01\x03\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+ERROR HY000: Illegal parameter data types int and geometry for operation '<>'
DROP TABLE t1;
#
# Bug #49250 : spatial btree index corruption and crash
@@ -1026,9 +1024,9 @@ f5 datetime YES NULL
drop view v1;
drop table t1;
SELECT MultiPoint(12345,'');
-ERROR 22007: Illegal non geometric '12345' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
-ERROR 22007: Illegal non geometric ''00000'' value found during parsing
+ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
#
# BUG#51875: crash when loading data into geometry function ST_polyfromwkb
#
@@ -1092,7 +1090,7 @@ ST_ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20)))
# GEOMETRY FUNCTION ARGUMENTS
#
SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
-ERROR 22007: Illegal non geometric '' value found during parsing
+ERROR HY000: Illegal parameter data type bigint for operation 'geometrycollection'
End of 5.1 tests
#
# Bug#11908153: CRASH AND/OR VALGRIND ERRORS IN FIELD_BLOB::GET_KEY_IMAGE
@@ -1105,11 +1103,7 @@ FLUSH TABLES;
SELECT 1 FROM g1
FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
;
-1
-Warnings:
-Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xF0?'
-Warning 1441 Datetime function: datetime field overflow
-Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\x00@'
+ERROR HY000: Illegal parameter data types geometry and datetime for operation '='
DROP TABLE g1;
#
# Bug#13013970 MORE CRASHES IN FIELD_BLOB::GET_KEY_IMAGE
@@ -1495,5 +1489,4 @@ DROP DATABASE gis_ogs;
# Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
#
SELECT ST_Union('', ''), md5(1);
-ST_Union('', '') md5(1)
-NULL c4ca4238a0b923820dcc509a6f75849b
+ERROR HY000: Illegal parameter data type varchar for operation 'st_union'
diff --git a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result
index a6279bdb196..abc3c5b5f05 100644
--- a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result
+++ b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result
@@ -257,6 +257,9 @@ ALTER TABLE tab DROP PRIMARY KEY;
ALTER TABLE tab DROP INDEX idx2;
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab where c1 = c2;
+ERROR HY000: Illegal parameter data types int and geometry for operation '='
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
+CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab;
INSERT INTO temp_tab SELECT * FROM tab;
CREATE SPATIAL INDEX idx2 ON temp_tab(c2);
CREATE SPATIAL INDEX idx3 ON temp_tab(c3);
diff --git a/mysql-test/suite/innodb_gis/r/create_spatial_index.result b/mysql-test/suite/innodb_gis/r/create_spatial_index.result
index 71d3092c3b7..fe46ef2e2f8 100644
--- a/mysql-test/suite/innodb_gis/r/create_spatial_index.result
+++ b/mysql-test/suite/innodb_gis/r/create_spatial_index.result
@@ -1241,13 +1241,15 @@ Table Op Msg_type Msg_text
test.tab check status OK
DROP TABLE tab;
CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB;
+ERROR HY000: Illegal parameter data types geometry and int for operation '>'
+CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB;
CREATE SPATIAL INDEX idx1 ON tab(c1) ;
SHOW CREATE TABLE tab;
Table Create Table
tab CREATE TABLE `tab` (
`c1` point NOT NULL,
SPATIAL KEY `idx1` (`c1`),
- CONSTRAINT `tab_const` CHECK (`c1` > 0)
+ CONSTRAINT `tab_const` CHECK (cast(`c1` as char charset binary) > 0)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SHOW INDEX FROM tab;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
diff --git a/mysql-test/suite/innodb_gis/r/gis.result b/mysql-test/suite/innodb_gis/r/gis.result
index c0a24a25feb..836a15bb295 100644
--- a/mysql-test/suite/innodb_gis/r/gis.result
+++ b/mysql-test/suite/innodb_gis/r/gis.result
@@ -681,7 +681,7 @@ def test t1 t1 g g 255 4294967295 0 Y 144 0 63
g
select ST_asbinary(g) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def ST_asbinary(g) 252 4294967295 0 Y 128 0 63
+def ST_asbinary(g) 251 4294967295 0 Y 128 0 63
ST_asbinary(g)
drop table t1;
create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
@@ -864,8 +864,8 @@ down3,left3,right3,up3
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRequals FROM t1 a1 JOIN t1 a2 ON MBREquals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
MBRequals
center
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-intersect
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+intersects
big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRoverlaps FROM t1 a1 JOIN t1 a2 ON MBROverlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
MBRoverlaps
@@ -992,9 +992,7 @@ ST_GEOMFROMTEXT(
'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))'));
# must not crash
SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
-1
-Warnings:
-Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x06\x00\x00\x00\x01\x00\x00\x00\x01\x03\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+ERROR HY000: Illegal parameter data types int and geometry for operation '<>'
DROP TABLE t1;
#
# Bug #49250 : spatial btree index corruption and crash
@@ -1022,9 +1020,9 @@ f5 datetime YES NULL
drop view v1;
drop table t1;
SELECT MultiPoint(12345,'');
-ERROR 22007: Illegal non geometric '12345' value found during parsing
+ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
-ERROR 22007: Illegal non geometric ''00000'' value found during parsing
+ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
#
# BUG#51875: crash when loading data into geometry function ST_polyfromwkb
#
@@ -1093,7 +1091,7 @@ ST_ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20)))
# GEOMETRY FUNCTION ARGUMENTS
#
SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
-ERROR 22007: Illegal non geometric '' value found during parsing
+ERROR HY000: Illegal parameter data type bigint for operation 'geometrycollection'
End of 5.1 tests
#
# Bug#11908153: CRASH AND/OR VALGRIND ERRORS IN FIELD_BLOB::GET_KEY_IMAGE
@@ -1106,11 +1104,7 @@ FLUSH TABLES;
SELECT 1 FROM g1
FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
;
-1
-Warnings:
-Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xF0?'
-Warning 1441 Datetime function: datetime field overflow
-Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\x00@'
+ERROR HY000: Illegal parameter data types geometry and datetime for operation '='
DROP TABLE g1;
#
# Bug#13013970 MORE CRASHES IN FIELD_BLOB::GET_KEY_IMAGE
@@ -1487,5 +1481,4 @@ DROP DATABASE gis_ogs;
# Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
#
SELECT ST_Union('', ''), md5(1);
-ST_Union('', '') md5(1)
-NULL c4ca4238a0b923820dcc509a6f75849b
+ERROR HY000: Illegal parameter data type varchar for operation 'st_union'
diff --git a/mysql-test/suite/innodb_gis/r/precise.result b/mysql-test/suite/innodb_gis/r/precise.result
index 9d6538bc3ed..3c05b814602 100644
--- a/mysql-test/suite/innodb_gis/r/precise.result
+++ b/mysql-test/suite/innodb_gis/r/precise.result
@@ -216,8 +216,7 @@ st_u
MULTIPOLYGON(((525400 18370,525000.9677614468 183300,525400 183300,525400 18370)),((525000 183300,525000 183700,525000.9677614468 183300,525000 183300)),((525265.58 183481.95,525263.95 183484.75,525260.7 183491.55,525276.79 183500,525278.39 183500.84,525278.63 183500.97,525280.98 183502.26,525283.17 183503.47,525289.11 183506.62,525296.42 183510.31,525296.57 183510.39,525298.67 183511.53,525302.81 183513.8,525304.5 183510.83,525307.85 183504.95,525304.45 183504.25,525301.75 183509.35,525283.55 183500,525282.2 183499.3,525282.3 183499.1,525280.35 183498.2,525275.5 183495.7,525276.5 183493.45,525278.97 183488.73,525265.58 183481.95),(525266.99 183484.33,525263.26 183491.55,525266.15 183493.04,525269.88 183485.82,525266.99 183484.33),(525272.06 183488.37,525268.94 183494.51,525271.94 183496.03,525275.06 183489.89,525272.06 183488.37)))
SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
SELECT ST_ASTEXT(ST_TOUCHES(@a, ST_GEOMFROMTEXT('point(0 0)'))) t;
-t
-NULL
+ERROR HY000: Illegal parameter data type int for operation 'st_astext'
DROP TABLE IF EXISTS p1;
CREATE PROCEDURE p1(dist DOUBLE, geom TEXT)
BEGIN
diff --git a/mysql-test/suite/innodb_gis/t/1.test b/mysql-test/suite/innodb_gis/t/1.test
index 110a8acc18f..0dd4d3262a2 100644
--- a/mysql-test/suite/innodb_gis/t/1.test
+++ b/mysql-test/suite/innodb_gis/t/1.test
@@ -616,7 +616,7 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRcontains FROM t1 a1 JOIN t1 a2 ON MBRContains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRdisjoint FROM t1 a1 JOIN t1 a2 ON MBRDisjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRequals FROM t1 a1 JOIN t1 a2 ON MBREquals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRoverlaps FROM t1 a1 JOIN t1 a2 ON MBROverlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS ST_touches FROM t1 a1 JOIN t1 a2 ON ST_Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
@@ -701,6 +701,7 @@ INSERT INTO t1 VALUES
'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))'));
--echo # must not crash
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
DROP TABLE t1;
@@ -737,7 +738,7 @@ drop table t1;
# Bug#44684: valgrind reports invalid reads in
# Item_func_spatial_collection::val_str
#
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT MultiPoint(12345,'');
#SELECT MultiPoint(123451,'');
#SELECT MultiPoint(1234512,'');
@@ -764,7 +765,7 @@ SELECT MultiPoint(12345,'');
#
# Bug55531 crash with conversions of geometry types / strings
#
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
@@ -867,7 +868,7 @@ SELECT ST_ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20)));
--echo # GEOMETRY FUNCTION ARGUMENTS
--echo #
--replace_regex /non geometric .* value/non geometric '' value/
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
@@ -886,6 +887,7 @@ INSERT INTO g1 VALUES (ST_geomfromtext('point(1 2)'));
FLUSH TABLES;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM g1
FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
;
@@ -1447,5 +1449,5 @@ DROP DATABASE gis_ogs;
--echo # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
--echo #
-# --error ER_GIS_INVALID_DATA
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_Union('', ''), md5(1);
diff --git a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test
index 80ecf95bef9..48052da021f 100644
--- a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test
+++ b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test
@@ -303,9 +303,13 @@ ALTER TABLE tab DROP PRIMARY KEY;
ALTER TABLE tab DROP INDEX idx2;
# Check spatial index on temp tables
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab where c1 = c2;
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
+CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab;
+
INSERT INTO temp_tab SELECT * FROM tab;
CREATE SPATIAL INDEX idx2 ON temp_tab(c2);
diff --git a/mysql-test/suite/innodb_gis/t/create_spatial_index.test b/mysql-test/suite/innodb_gis/t/create_spatial_index.test
index d25a2e79793..f8626b3c052 100644
--- a/mysql-test/suite/innodb_gis/t/create_spatial_index.test
+++ b/mysql-test/suite/innodb_gis/t/create_spatial_index.test
@@ -1118,7 +1118,9 @@ DROP TABLE tab;
# End of Testcase compress table with Auto_increment
# Test check constraint on spatial column
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB;
+CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB;
CREATE SPATIAL INDEX idx1 ON tab(c1) ;
diff --git a/mysql-test/suite/innodb_gis/t/gis.test b/mysql-test/suite/innodb_gis/t/gis.test
index f28809f393c..8087f6be82e 100644
--- a/mysql-test/suite/innodb_gis/t/gis.test
+++ b/mysql-test/suite/innodb_gis/t/gis.test
@@ -610,7 +610,7 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRcontains FROM t1 a1 JOIN t1 a2 ON MBRContains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRdisjoint FROM t1 a1 JOIN t1 a2 ON MBRDisjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRequals FROM t1 a1 JOIN t1 a2 ON MBREquals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRoverlaps FROM t1 a1 JOIN t1 a2 ON MBROverlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS ST_touches FROM t1 a1 JOIN t1 a2 ON ST_Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
@@ -695,6 +695,7 @@ INSERT INTO t1 VALUES
'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))'));
--echo # must not crash
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
DROP TABLE t1;
@@ -731,7 +732,7 @@ drop table t1;
# Bug#44684: valgrind reports invalid reads in
# Item_func_spatial_collection::val_str
#
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT MultiPoint(12345,'');
#SELECT MultiPoint(123451,'');
#SELECT MultiPoint(1234512,'');
@@ -758,7 +759,7 @@ SELECT MultiPoint(12345,'');
#
# Bug55531 crash with conversions of geometry types / strings
#
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
@@ -869,7 +870,7 @@ SELECT ST_ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20)));
--echo # GEOMETRY FUNCTION ARGUMENTS
--echo #
--replace_regex /non geometric .* value/non geometric '' value/
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
@@ -888,6 +889,7 @@ INSERT INTO g1 VALUES (ST_geomfromtext('point(1 2)'));
FLUSH TABLES;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM g1
FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
;
@@ -1441,4 +1443,5 @@ DROP DATABASE gis_ogs;
--echo #
# --error ER_GIS_INVALID_DATA
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_Union('', ''), md5(1);
diff --git a/mysql-test/suite/innodb_gis/t/precise.test b/mysql-test/suite/innodb_gis/t/precise.test
index 9174a100003..08b7e348362 100644
--- a/mysql-test/suite/innodb_gis/t/precise.test
+++ b/mysql-test/suite/innodb_gis/t/precise.test
@@ -140,7 +140,7 @@ ST_geomfromtext('POLYGON((525298.67 183511.53,525296.57
183491.55))'))) st_u;
SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
-# --error ER_GIS_INVALID_DATA
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_ASTEXT(ST_TOUCHES(@a, ST_GEOMFROMTEXT('point(0 0)'))) t;
diff --git a/mysql-test/suite/maria/ps_maria.result b/mysql-test/suite/maria/ps_maria.result
index bc03e40a717..bd5f2b4c55b 100644
--- a/mysql-test/suite/maria/ps_maria.result
+++ b/mysql-test/suite/maria/ps_maria.result
@@ -1932,26 +1932,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
@@ -1979,26 +1979,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select
@@ -2029,26 +2029,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2069,26 +2069,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select ? := c1 from t9 where c1= 1" ;
@@ -2117,26 +2117,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2161,26 +2161,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
@@ -2207,26 +2207,26 @@ def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
def @arg11 246 83 6 Y 32896 38 63
def @arg12 246 83 6 Y 32896 38 63
-def @arg13 250 16777215 10 Y 0 39 8
-def @arg14 250 16777215 19 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 8 Y 0 39 8
+def @arg13 251 16777215 10 Y 0 39 8
+def @arg14 251 16777215 19 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 8 Y 0 39 8
def @arg17 8 20 4 Y 32928 0 63
def @arg18 8 20 1 Y 32896 0 63
def @arg19 8 20 1 Y 32896 0 63
-def @arg20 250 16777215 1 Y 0 39 8
-def @arg21 250 16777215 10 Y 0 39 8
-def @arg22 250 16777215 30 Y 0 39 8
-def @arg23 250 16777215 8 Y 128 39 63
-def @arg24 250 16777215 8 Y 0 39 8
-def @arg25 250 16777215 4 Y 128 39 63
-def @arg26 250 16777215 4 Y 0 39 8
-def @arg27 250 16777215 10 Y 128 39 63
-def @arg28 250 16777215 10 Y 0 39 8
-def @arg29 250 16777215 8 Y 128 39 63
-def @arg30 250 16777215 8 Y 0 39 8
-def @arg31 250 16777215 3 Y 0 39 8
-def @arg32 250 16777215 6 Y 0 39 8
+def @arg20 251 16777215 1 Y 0 39 8
+def @arg21 251 16777215 10 Y 0 39 8
+def @arg22 251 16777215 30 Y 0 39 8
+def @arg23 251 16777215 8 Y 128 39 63
+def @arg24 251 16777215 8 Y 0 39 8
+def @arg25 251 16777215 4 Y 128 39 63
+def @arg26 251 16777215 4 Y 0 39 8
+def @arg27 251 16777215 10 Y 128 39 63
+def @arg28 251 16777215 10 Y 0 39 8
+def @arg29 251 16777215 8 Y 128 39 63
+def @arg30 251 16777215 8 Y 0 39 8
+def @arg31 251 16777215 3 Y 0 39 8
+def @arg32 251 16777215 6 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday
set @my_key= 0 ;
@@ -2245,26 +2245,26 @@ def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
def @arg11 246 83 0 Y 32896 38 63
def @arg12 246 83 0 Y 32896 38 63
-def @arg13 250 16777215 0 Y 0 39 8
-def @arg14 250 16777215 0 Y 0 39 8
-def @arg15 250 16777215 19 Y 0 39 8
-def @arg16 250 16777215 0 Y 0 39 8
+def @arg13 251 16777215 0 Y 0 39 8
+def @arg14 251 16777215 0 Y 0 39 8
+def @arg15 251 16777215 19 Y 0 39 8
+def @arg16 251 16777215 0 Y 0 39 8
def @arg17 8 20 0 Y 32928 0 63
def @arg18 8 20 0 Y 32896 0 63
def @arg19 8 20 0 Y 32896 0 63
-def @arg20 250 16777215 0 Y 0 39 8
-def @arg21 250 16777215 0 Y 0 39 8
-def @arg22 250 16777215 0 Y 0 39 8
-def @arg23 250 16777215 0 Y 128 39 63
-def @arg24 250 16777215 0 Y 0 39 8
-def @arg25 250 16777215 0 Y 128 39 63
-def @arg26 250 16777215 0 Y 0 39 8
-def @arg27 250 16777215 0 Y 128 39 63
-def @arg28 250 16777215 0 Y 0 39 8
-def @arg29 250 16777215 0 Y 128 39 63
-def @arg30 250 16777215 0 Y 0 39 8
-def @arg31 250 16777215 0 Y 0 39 8
-def @arg32 250 16777215 0 Y 0 39 8
+def @arg20 251 16777215 0 Y 0 39 8
+def @arg21 251 16777215 0 Y 0 39 8
+def @arg22 251 16777215 0 Y 0 39 8
+def @arg23 251 16777215 0 Y 128 39 63
+def @arg24 251 16777215 0 Y 0 39 8
+def @arg25 251 16777215 0 Y 128 39 63
+def @arg26 251 16777215 0 Y 0 39 8
+def @arg27 251 16777215 0 Y 128 39 63
+def @arg28 251 16777215 0 Y 0 39 8
+def @arg29 251 16777215 0 Y 128 39 63
+def @arg30 251 16777215 0 Y 0 39 8
+def @arg31 251 16777215 0 Y 0 39 8
+def @arg32 251 16777215 0 Y 0 39 8
@arg01 @arg02 @arg03 @arg04 @arg05 @arg06 @arg07 @arg08 @arg09 @arg10 @arg11 @arg12 @arg13 @arg14 @arg15 @arg16 @arg17 @arg18 @arg19 @arg20 @arg21 @arg22 @arg23 @arg24 @arg25 @arg26 @arg27 @arg28 @arg29 @arg30 @arg31 @arg32
0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1991-01-01 01:01:01 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
prepare stmt1 from "select c1 into ? from t9 where c1= 1" ;
diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result
index 4c123663597..83510e5827e 100644
--- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result
+++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result
@@ -21,6 +21,7 @@ order by name limit 10;
NAME ENABLED TIMED
wait/synch/rwlock/sql/LOCK_dboptions YES YES
wait/synch/rwlock/sql/LOCK_grant YES YES
+wait/synch/rwlock/sql/LOCK_SEQUENCE YES YES
wait/synch/rwlock/sql/LOCK_system_variables_hash YES YES
wait/synch/rwlock/sql/LOCK_sys_init_connect YES YES
wait/synch/rwlock/sql/LOCK_sys_init_slave YES YES
@@ -28,7 +29,6 @@ wait/synch/rwlock/sql/LOGGER::LOCK_logger YES YES
wait/synch/rwlock/sql/MDL_context::LOCK_waiting_for YES YES
wait/synch/rwlock/sql/MDL_lock::rwlock YES YES
wait/synch/rwlock/sql/Query_cache_query::lock YES YES
-wait/synch/rwlock/sql/THR_LOCK_servers YES YES
select * from performance_schema.setup_instruments
where name like 'Wait/Synch/Cond/sql/%'
and name not in (
diff --git a/mysql-test/suite/perfschema/r/view_table_io.result b/mysql-test/suite/perfschema/r/view_table_io.result
index 5d8ad26ae77..2f9a70cdeaa 100644
--- a/mysql-test/suite/perfschema/r/view_table_io.result
+++ b/mysql-test/suite/perfschema/r/view_table_io.result
@@ -51,7 +51,7 @@ bar 2
insert into marker set a = 1;
optimize table test.v1;
Table Op Msg_type Msg_text
-test.v1 optimize Error 'test.v1' is not BASE TABLE
+test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE'
test.v1 optimize status Operation failed
insert into marker set a = 1;
select * from test.v1;
diff --git a/mysql-test/suite/rpl/r/rpl_charset.result b/mysql-test/suite/rpl/r/rpl_charset.result
index a96cb26dd9d..5bda623172b 100644
--- a/mysql-test/suite/rpl/r/rpl_charset.result
+++ b/mysql-test/suite/rpl/r/rpl_charset.result
@@ -121,4 +121,27 @@ primary key (`pk`)
set @p=_latin1 'test';
update t1 set pk='test' where pk=@p;
drop table t1;
+#
+# Start of 10.3 tests
+#
+#
+# MDEV-12685 Oracle-compatible function CHR()
+#
+connection master;
+CREATE DATABASE db1 DEFAULT CHARACTER SET latin1 COLLATE latin1_bin;
+USE db1;
+CREATE TABLE t1 AS SELECT CHR(0x60);
+connection slave;
+SHOW CREATE TABLE db1.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CHR(0x60)` varchar(4) COLLATE latin1_bin DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_bin
+connection master;
+USE test;
+DROP DATABASE db1;
+connection slave;
+#
+# End of 10.3 tests
+#
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_create_drop_trigger.result b/mysql-test/suite/rpl/r/rpl_create_drop_trigger.result
index 76024d1fd74..e1474d8854e 100644
--- a/mysql-test/suite/rpl/r/rpl_create_drop_trigger.result
+++ b/mysql-test/suite/rpl/r/rpl_create_drop_trigger.result
@@ -19,7 +19,7 @@ SET @sum = @sum + NEW.val + 1
connection master;
CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 2;
Warnings:
-Note 1359 Trigger already exists
+Note 1359 Trigger 'db1.val_sum' already exists
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
ACTION_STATEMENT_Master
SET @sum = @sum + NEW.val + 1
diff --git a/mysql-test/suite/rpl/r/rpl_create_drop_view.result b/mysql-test/suite/rpl/r/rpl_create_drop_view.result
index fef1edb2018..0c18249ca08 100644
--- a/mysql-test/suite/rpl/r/rpl_create_drop_view.result
+++ b/mysql-test/suite/rpl/r/rpl_create_drop_view.result
@@ -96,10 +96,10 @@ connection master;
DROP VIEW v1;
DROP TABLE t1;
DROP VIEW v1;
-ERROR 42S02: Unknown table 'test.v1'
+ERROR 42S02: Unknown VIEW: 'test.v1'
DROP VIEW IF EXISTS v2;
Warnings:
-Note 1051 Unknown table 'test.v2'
+Note 4068 Unknown VIEW: 'test.v2'
# Syncing slave with master
connection slave;
SELECT * FROM v1;
diff --git a/mysql-test/suite/rpl/r/rpl_drop_view.result b/mysql-test/suite/rpl/r/rpl_drop_view.result
index f6ced4eb41f..aa4df701609 100644
--- a/mysql-test/suite/rpl/r/rpl_drop_view.result
+++ b/mysql-test/suite/rpl/r/rpl_drop_view.result
@@ -9,9 +9,9 @@ create view v1 as select * from t1;
create view v2 as select * from t2;
create view v3 as select * from t3;
drop view not_exist_view;
-ERROR 42S02: Unknown table 'test.not_exist_view'
+ERROR 42S02: Unknown VIEW: 'test.not_exist_view'
drop view v1, not_exist_view;
-ERROR 42S02: Unknown table 'test.not_exist_view'
+ERROR 42S02: Unknown VIEW: 'test.not_exist_view'
select * from v1;
ERROR 42S02: Table 'test.v1' doesn't exist
drop view v2, v3;
diff --git a/mysql-test/suite/rpl/r/rpl_slave_grp_exec.result b/mysql-test/suite/rpl/r/rpl_slave_grp_exec.result
index 9a34844489f..60ad6dc6e4f 100644
--- a/mysql-test/suite/rpl/r/rpl_slave_grp_exec.result
+++ b/mysql-test/suite/rpl/r/rpl_slave_grp_exec.result
@@ -35,6 +35,7 @@ a b
1 ZZ
connection slave;
call mtr.add_suppression("Slave SQL.*Table .test.t3. doesn.t exist.* error.* 1146");
+call mtr.add_suppression("At line *");
include/wait_for_slave_sql_error.inc [errno=1146]
SHOW TABLES LIKE 't%';
Tables_in_test (t%)
diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result
index 411a24278d5..3ea69a1e391 100644
--- a/mysql-test/suite/rpl/r/rpl_sp.result
+++ b/mysql-test/suite/rpl/r/rpl_sp.result
@@ -128,6 +128,7 @@ show warnings;
Level Code Message
Error 1062 Duplicate entry '20' for key 'a'
Warning 1196 Some non-transactional changed tables couldn't be rolled back
+Note 4070 At line 4 in mysqltest1.foo4
select * from t2;
a
20
@@ -290,6 +291,7 @@ end|
do fn1(100);
Warnings:
Error 1062 Duplicate entry '100' for key 'a'
+Note 4070 At line 3 in mysqltest1.fn1
Warning 1196 Some non-transactional changed tables couldn't be rolled back
select fn1(20);
ERROR 23000: Duplicate entry '20' for key 'a'
diff --git a/mysql-test/suite/rpl/r/rpl_stm_sp.result b/mysql-test/suite/rpl/r/rpl_stm_sp.result
new file mode 100644
index 00000000000..4e2d4c80fb6
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_stm_sp.result
@@ -0,0 +1,26 @@
+include/master-slave.inc
+[connection master]
+#
+# MDEV-11815 SP variables of temporal data types do not replicate correctly
+#
+connection master;
+CREATE TABLE t1(a INT);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a TIME DEFAULT '01:01:01';
+INSERT INTO t1 VALUES (a=10101);
+END;
+$$
+CALL p1;
+SELECT * FROM t1;
+a
+1
+connection slave;
+SELECT * FROM t1;
+a
+1
+connection master;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+connection slave;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/rpl_trans_no_trans.result b/mysql-test/suite/rpl/r/rpl_trans_no_trans.result
new file mode 100644
index 00000000000..a7a6d921bc1
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_trans_no_trans.result
@@ -0,0 +1,44 @@
+include/master-slave.inc
+[connection master]
+create or replace table t1(id int)engine=innodb;
+create or replace table t3(id int)engine=myisam;
+create or replace function t99 (a int)
+returns int(10)
+MODIFIES SQL DATA
+begin
+if (a > 100)
+then
+insert into t3 values (a);
+end if;
+return a;
+end//
+begin;
+insert into t1 values(t99(1));
+insert into t1 values(t99(101));
+commit;
+select * from t1;
+id
+1
+101
+select * from t3;
+id
+101
+insert into t1 values(t99(1));
+drop function t99;
+drop table t1,t3;
+connection slave;
+connection master;
+CREATE TABLE t1 (i INT) ENGINE=InnoDB;
+CREATE TABLE t2 (j INT) ENGINE=MyISAM;
+CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+SET @a = unknown_column_just_to_raise_an_error;
+INSERT INTO t2 VALUES (NULL) ;
+END||
+INSERT INTO t1 VALUES (1);
+ERROR 42S22: Unknown column 'unknown_column_just_to_raise_an_error' in 'field list'
+connection slave;
+connection master;
+drop trigger tr;
+drop table t1,t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/r/sequence.result b/mysql-test/suite/rpl/r/sequence.result
new file mode 100644
index 00000000000..6286c5c7106
--- /dev/null
+++ b/mysql-test/suite/rpl/r/sequence.result
@@ -0,0 +1,129 @@
+include/rpl_init.inc [topology=1->2->3]
+include/rpl_connect.inc [creating master]
+include/rpl_connect.inc [creating slave]
+include/rpl_connect.inc [creating slave2]
+connection master;
+set @@default_storage_engine="aria";
+CREATE SEQUENCE s1 cache=10;
+create table t1 select * from s1;
+select NEXT VALUE for s1,seq from seq_1_to_20;
+NEXT VALUE for s1 seq
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+10 10
+11 11
+12 12
+13 13
+14 14
+15 15
+16 16
+17 17
+18 18
+19 19
+20 20
+insert into t1 select * from s1;
+do setval(s1,5, 1, 0);
+insert into t1 select * from s1;
+do setval(s1, 5000, 1 ,0);
+insert into t1 select * from s1;
+alter sequence s1 minvalue=-1 start=-1 restart=-1;
+insert into t1 select * from s1;
+insert into s1 values(-100,-1000,9223372036854775806,1,1,1000,0,0);
+insert into t1 select * from s1;
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 10 0 0
+21 1 9223372036854775806 1 1 10 0 0
+21 1 9223372036854775806 1 1 10 0 0
+5001 1 9223372036854775806 1 1 10 0 0
+-1 -1 9223372036854775806 -1 1 10 0 0
+-100 -1000 9223372036854775806 1 1 1000 0 0
+connection slave;
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 10 0 0
+21 1 9223372036854775806 1 1 10 0 0
+21 1 9223372036854775806 1 1 10 0 0
+5001 1 9223372036854775806 1 1 10 0 0
+-1 -1 9223372036854775806 -1 1 10 0 0
+-100 -1000 9223372036854775806 1 1 1000 0 0
+connection slave2;
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 10 0 0
+21 1 9223372036854775806 1 1 10 0 0
+21 1 9223372036854775806 1 1 10 0 0
+5001 1 9223372036854775806 1 1 10 0 0
+-1 -1 9223372036854775806 -1 1 10 0 0
+-100 -1000 9223372036854775806 1 1 1000 0 0
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE SEQUENCE s1 cache=10
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) PAGE_CHECKSUM=1
+master-bin.000001 # Annotate_rows # # create table t1 select * from s1
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # select NEXT VALUE for s1,seq from seq_1_to_20
+master-bin.000001 # Table_map # # table_id: # (test.s1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # insert into t1 select * from s1
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # insert into t1 select * from s1
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # do setval(s1, 5000, 1 ,0)
+master-bin.000001 # Table_map # # table_id: # (test.s1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # insert into t1 select * from s1
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; alter sequence s1 minvalue=-1 start=-1 restart=-1
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # insert into t1 select * from s1
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # insert into s1 values(-100,-1000,9223372036854775806,1,1,1000,0,0)
+master-bin.000001 # Table_map # # table_id: # (test.s1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # insert into t1 select * from s1
+master-bin.000001 # Table_map # # table_id: # (test.t1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+connection master;
+drop table s1,t1;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_view.test b/mysql-test/suite/rpl/t/rpl_create_drop_view.test
index 9280f35f638..c26243ab3c6 100644
--- a/mysql-test/suite/rpl/t/rpl_create_drop_view.test
+++ b/mysql-test/suite/rpl/t/rpl_create_drop_view.test
@@ -41,7 +41,7 @@ connection master;
DROP VIEW v1;
DROP TABLE t1;
---error ER_BAD_TABLE_ERROR
+--error ER_UNKNOWN_VIEW
DROP VIEW v1;
DROP VIEW IF EXISTS v2;
diff --git a/mysql-test/suite/rpl/t/rpl_drop_view.test b/mysql-test/suite/rpl/t/rpl_drop_view.test
index 55a0ea104d8..1893dd21926 100644
--- a/mysql-test/suite/rpl/t/rpl_drop_view.test
+++ b/mysql-test/suite/rpl/t/rpl_drop_view.test
@@ -13,9 +13,9 @@ create table t3 (c int);
create view v1 as select * from t1;
create view v2 as select * from t2;
create view v3 as select * from t3;
---error 1051
+--error ER_UNKNOWN_VIEW
drop view not_exist_view;
---error 1051
+--error ER_UNKNOWN_VIEW
drop view v1, not_exist_view;
--error 1146
select * from v1;
diff --git a/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test b/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test
index 426c3c831b0..928ad7e5e09 100644
--- a/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test
+++ b/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test
@@ -64,6 +64,7 @@ SELECT * FROM t3 ORDER BY a;
--connection slave
# 1146 = ER_NO_SUCH_TABLE
call mtr.add_suppression("Slave SQL.*Table .test.t3. doesn.t exist.* error.* 1146");
+call mtr.add_suppression("At line *");
--let $slave_sql_errno= 1146
--source include/wait_for_slave_sql_error.inc
SHOW TABLES LIKE 't%';
diff --git a/mysql-test/suite/rpl/t/rpl_stm_sp.test b/mysql-test/suite/rpl/t/rpl_stm_sp.test
new file mode 100644
index 00000000000..b99906b8d03
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_stm_sp.test
@@ -0,0 +1,30 @@
+--source include/have_binlog_format_statement.inc
+--source include/master-slave.inc
+
+--echo #
+--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly
+--echo #
+
+connection master;
+CREATE TABLE t1(a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TIME DEFAULT '01:01:01';
+ INSERT INTO t1 VALUES (a=10101);
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+SELECT * FROM t1;
+
+sync_slave_with_master;
+SELECT * FROM t1;
+
+connection master;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+sync_slave_with_master;
+
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_trans_no_trans.test b/mysql-test/suite/rpl/t/rpl_trans_no_trans.test
new file mode 100644
index 00000000000..f6e3731dbf8
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_trans_no_trans.test
@@ -0,0 +1,72 @@
+#
+# Test mixing transactional and non transactional tables
+#
+
+--source include/master-slave.inc
+--source include/have_innodb.inc
+--source include/have_binlog_format_row.inc
+
+#
+# Test updating conditionally a non transactinal table in a function
+# This verifies that we don't write only a table map for a non transactional,
+# without any row events
+# The original bug caused a crash on the slave when doing a sync_slave
+#
+
+create or replace table t1(id int)engine=innodb;
+create or replace table t3(id int)engine=myisam;
+
+delimiter //;
+create or replace function t99 (a int)
+returns int(10)
+MODIFIES SQL DATA
+begin
+ if (a > 100)
+ then
+ insert into t3 values (a);
+ end if;
+ return a;
+end//
+delimiter ;//
+begin;
+insert into t1 values(t99(1));
+insert into t1 values(t99(101));
+commit;
+select * from t1;
+select * from t3;
+insert into t1 values(t99(1));
+
+drop function t99;
+drop table t1,t3;
+
+sync_slave_with_master;
+connection master;
+
+#
+# MDEV-8203
+# Assertion `!current_stmt_is_commit || !rgi->tables_to_lock' failed in
+# Query_log_event::do_apply_event(rpl_group_info*, const char*, uint32)
+#
+
+CREATE TABLE t1 (i INT) ENGINE=InnoDB;
+CREATE TABLE t2 (j INT) ENGINE=MyISAM;
+
+--delimiter ||
+CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+ SET @a = unknown_column_just_to_raise_an_error;
+ INSERT INTO t2 VALUES (NULL) ;
+END||
+--delimiter ;
+
+--error ER_BAD_FIELD_ERROR
+INSERT INTO t1 VALUES (1);
+--sync_slave_with_master
+
+connection master;
+
+drop trigger tr;
+drop table t1,t2;
+
+# End of 4.1 tests
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/sequence.cnf b/mysql-test/suite/rpl/t/sequence.cnf
new file mode 100644
index 00000000000..58b605ad928
--- /dev/null
+++ b/mysql-test/suite/rpl/t/sequence.cnf
@@ -0,0 +1,8 @@
+!include ../my.cnf
+
+[mysqld.3]
+log-slave-updates
+
+[ENV]
+SERVER_MYPORT_3= @mysqld.3.port
+SERVER_MYSOCK_3= @mysqld.3.socket
diff --git a/mysql-test/suite/rpl/t/sequence.test b/mysql-test/suite/rpl/t/sequence.test
new file mode 100644
index 00000000000..436a0b1cdab
--- /dev/null
+++ b/mysql-test/suite/rpl/t/sequence.test
@@ -0,0 +1,52 @@
+#
+# Testing sequences with replication
+#
+
+--source include/have_binlog_format_row.inc
+--source include/have_aria.inc
+--source include/have_sequence.inc
+
+--let $rpl_topology= 1->2->3
+--source include/rpl_init.inc
+
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave2
+--let $rpl_server_number= 3
+--source include/rpl_connect.inc
+
+--connection master
+
+set @@default_storage_engine="aria";
+
+CREATE SEQUENCE s1 cache=10;
+create table t1 select * from s1;
+select NEXT VALUE for s1,seq from seq_1_to_20;
+insert into t1 select * from s1;
+do setval(s1,5, 1, 0);
+insert into t1 select * from s1;
+do setval(s1, 5000, 1 ,0);
+insert into t1 select * from s1;
+alter sequence s1 minvalue=-1 start=-1 restart=-1;
+insert into t1 select * from s1;
+insert into s1 values(-100,-1000,9223372036854775806,1,1,1000,0,0);
+insert into t1 select * from s1;
+select * from t1;
+--sync_slave_with_master
+select * from t1;
+--sync_slave_with_master slave2
+select * from t1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+connection master;
+drop table s1,t1;
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result
new file mode 100644
index 00000000000..76ebdeda0f7
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/alter.result
@@ -0,0 +1,240 @@
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+#
+# Test alter sequence
+#
+CREATE SEQUENCE t1 nocache engine=myisam;
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 0 0 0
+select next value for t1;
+next value for t1
+1
+alter sequence t1 start=50;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 50 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+2 1 9223372036854775806 50 1 0 0 0
+select next value for t1;
+next value for t1
+2
+alter sequence t1 minvalue=-100;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 50 minvalue -100 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 -100 9223372036854775806 50 1 0 0 0
+alter sequence t1 minvalue=100 start=100;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+alter sequence t1 minvalue=100 start=100 restart=100;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 100 minvalue 100 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+100 100 9223372036854775806 100 1 0 0 0
+alter sequence t1 maxvalue=500;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 100 minvalue 100 maxvalue 500 increment by 1 nocache nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+100 100 500 100 1 0 0 0
+drop sequence t1;
+CREATE SEQUENCE t1 engine=myisam;
+alter sequence t1 nocache;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
+alter sequence t1 cache=100;
+flush tables;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 100 nocycle ENGINE=MyISAM
+alter sequence t1 nocache;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
+flush tables;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 0 0 0
+select next value for t1;
+next value for t1
+1
+select next value for t1;
+next value for t1
+2
+select next value for t1;
+next value for t1
+3
+select next_not_cached_value, cycle_count from t1;
+next_not_cached_value cycle_count
+4 0
+drop sequence t1;
+CREATE SEQUENCE t1 maxvalue=100 engine=myisam;
+alter sequence t1 no maxvalue;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+alter sequence t1 cycle;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 cycle ENGINE=MyISAM
+alter sequence t1 nocycle;
+alter sequence t1 start=15 restart minvalue=10 maxvalue=20 cycle;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 15 minvalue 10 maxvalue 20 increment by 1 cache 1000 cycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+15 10 20 15 1 1000 1 0
+select NEXT VALUE for t1 from seq_1_to_10;
+NEXT VALUE for t1
+15
+16
+17
+18
+19
+20
+10
+11
+12
+13
+alter sequence t1 restart with 17 minvalue=10 maxvalue=20 cycle;
+select NEXT VALUE for t1 from seq_1_to_10;
+NEXT VALUE for t1
+17
+18
+19
+20
+10
+11
+12
+13
+14
+15
+drop sequence t1;
+CREATE SEQUENCE t1 maxvalue=100;
+alter sequence t1 increment=-2 start with 50 minvalue=-100;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 50 minvalue -100 maxvalue 100 increment by -2 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 -100 100 50 -2 1000 0 0
+select NEXT VALUE for t1 from seq_1_to_10;
+NEXT VALUE for t1
+1
+-1
+-3
+-5
+-7
+-9
+-11
+-13
+-15
+-17
+drop sequence t1;
+#
+# InnoDB (some things work different with InnoDB)
+
+CREATE SEQUENCE t1 cache 10 engine=innodb;
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 10 0 0
+select next value for t1;
+next value for t1
+1
+alter sequence t1 start=100;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 100 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 10 nocycle ENGINE=InnoDB
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 9223372036854775806 100 1 10 0 0
+select next value for t1;
+next value for t1
+11
+drop sequence t1;
+#
+# ALTER TABLE
+#
+CREATE SEQUENCE t1 engine=innodb;
+select next value for t1;
+next value for t1
+1
+alter table t1 rename t2;
+select next value for t2;
+next value for t2
+1001
+rename table t2 to t1;
+select next value for t1;
+next value for t1
+2001
+alter table t1 comment="foo";
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB COMMENT='foo'
+alter table t1 engine=myisam;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM COMMENT='foo'
+alter table t1 engine=innodb;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB COMMENT='foo'
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3001 1 9223372036854775806 1 1 1000 0 0
+drop sequence t1;
+CREATE SEQUENCE t1 engine=myisam;
+alter sequence t1 minvalue=100;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+drop sequence t1;
+CREATE SEQUENCE t1 engine=myisam;
+alter sequence t1 minvalue=25 maxvalue=20;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+drop sequence t1;
+create table t1 (a int);
+alter sequence t1 minvalue=100;
+ERROR 42S02: 'test.t1' is not a SEQUENCE
+drop table t1;
+alter sequence if exists t1 minvalue=100;
+Warnings:
+Note 4067 Unknown SEQUENCE: 'test.t1'
+alter sequence t1 minvalue=100;
+ERROR 42S02: Table 'test.t1' doesn't exist
+create sequence t1;
+alter sequence t1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
+drop sequence t1;
+CREATE SEQUENCE t1 maxvalue=100;
+alter sequence t1 increment=-2 start with 50;
+select next value for t1;
+next value for t1
+1
+select next value for t1;
+ERROR HY000: Sequence 'test.t1' has run out
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+0 1 100 50 -2 1000 0 0
+alter sequence t1 restart;
+select next value for t1;
+next value for t1
+50
+alter sequence t1 restart with 90;
+select next value for t1;
+next value for t1
+90
+drop sequence t1;
diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test
new file mode 100644
index 00000000000..fd1809ccd2f
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/alter.test
@@ -0,0 +1,141 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+
+drop table if exists t1;
+
+--echo #
+--echo # Test alter sequence
+--echo #
+
+CREATE SEQUENCE t1 nocache engine=myisam;
+select * from t1;
+select next value for t1;
+alter sequence t1 start=50;
+show create sequence t1;
+select * from t1;
+select next value for t1;
+
+alter sequence t1 minvalue=-100;
+show create sequence t1;
+select * from t1;
+--error ER_SEQUENCE_INVALID_DATA
+alter sequence t1 minvalue=100 start=100;
+alter sequence t1 minvalue=100 start=100 restart=100;
+show create sequence t1;
+select * from t1;
+
+alter sequence t1 maxvalue=500;
+show create sequence t1;
+select * from t1;
+drop sequence t1;
+
+CREATE SEQUENCE t1 engine=myisam;
+alter sequence t1 nocache;
+show create sequence t1;
+alter sequence t1 cache=100;
+flush tables;
+show create sequence t1;
+alter sequence t1 nocache;
+show create sequence t1;
+flush tables;
+show create sequence t1;
+select * from t1;
+select next value for t1;
+select next value for t1;
+select next value for t1;
+select next_not_cached_value, cycle_count from t1;
+drop sequence t1;
+
+CREATE SEQUENCE t1 maxvalue=100 engine=myisam;
+alter sequence t1 no maxvalue;
+show create sequence t1;
+select * from t1;
+alter sequence t1 cycle;
+show create sequence t1;
+alter sequence t1 nocycle;
+alter sequence t1 start=15 restart minvalue=10 maxvalue=20 cycle;
+show create sequence t1;
+select * from t1;
+select NEXT VALUE for t1 from seq_1_to_10;
+alter sequence t1 restart with 17 minvalue=10 maxvalue=20 cycle;
+select NEXT VALUE for t1 from seq_1_to_10;
+drop sequence t1;
+
+CREATE SEQUENCE t1 maxvalue=100;
+alter sequence t1 increment=-2 start with 50 minvalue=-100;
+show create sequence t1;
+select * from t1;
+select NEXT VALUE for t1 from seq_1_to_10;
+drop sequence t1;
+
+--echo #
+--echo # InnoDB (some things work different with InnoDB)
+--echo
+
+CREATE SEQUENCE t1 cache 10 engine=innodb;
+select * from t1;
+select next value for t1;
+alter sequence t1 start=100;
+show create sequence t1;
+select * from t1;
+select next value for t1;
+drop sequence t1;
+
+--echo #
+--echo # ALTER TABLE
+--echo #
+
+CREATE SEQUENCE t1 engine=innodb;
+select next value for t1;
+alter table t1 rename t2;
+select next value for t2;
+rename table t2 to t1;
+select next value for t1;
+alter table t1 comment="foo";
+show create sequence t1;
+alter table t1 engine=myisam;
+show create sequence t1;
+alter table t1 engine=innodb;
+show create sequence t1;
+select * from t1;
+drop sequence t1;
+
+#
+# Some error testing
+#
+
+CREATE SEQUENCE t1 engine=myisam;
+--error ER_SEQUENCE_INVALID_DATA
+alter sequence t1 minvalue=100;
+drop sequence t1;
+
+CREATE SEQUENCE t1 engine=myisam;
+--error ER_SEQUENCE_INVALID_DATA
+alter sequence t1 minvalue=25 maxvalue=20;
+drop sequence t1;
+
+create table t1 (a int);
+--error ER_NOT_SEQUENCE
+alter sequence t1 minvalue=100;
+drop table t1;
+
+alter sequence if exists t1 minvalue=100;
+--error ER_NO_SUCH_TABLE
+alter sequence t1 minvalue=100;
+
+create sequence t1;
+--error ER_PARSE_ERROR
+alter sequence t1;
+drop sequence t1;
+
+CREATE SEQUENCE t1 maxvalue=100;
+alter sequence t1 increment=-2 start with 50;
+select next value for t1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for t1;
+select * from t1;
+alter sequence t1 restart;
+select next value for t1;
+alter sequence t1 restart with 90;
+select next value for t1;
+drop sequence t1;
diff --git a/mysql-test/suite/sql_sequence/aria.result b/mysql-test/suite/sql_sequence/aria.result
new file mode 100644
index 00000000000..b39d85d58ca
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/aria.result
@@ -0,0 +1,66 @@
+set @@default_storage_engine="aria";
+CREATE SEQUENCE t1 cache=10;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 10 nocycle ENGINE=Aria
+select NEXT VALUE for t1,seq from seq_1_to_20;
+NEXT VALUE for t1 seq
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+10 10
+11 11
+12 12
+13 13
+14 14
+15 15
+16 16
+17 17
+18 18
+19 19
+20 20
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+21 1 9223372036854775806 1 1 10 0 0
+drop sequence t1;
+create sequence s1;
+check table s1;
+Table Op Msg_type Msg_text
+test.s1 check note The storage engine for the table doesn't support check
+select next value for s1;
+next value for s1
+1
+flush tables;
+check table s1;
+Table Op Msg_type Msg_text
+test.s1 check note The storage engine for the table doesn't support check
+select next value for s1;
+next value for s1
+1001
+flush tables;
+repair table s1;
+Table Op Msg_type Msg_text
+test.s1 repair status OK
+select next value for s1;
+next value for s1
+2001
+drop sequence s1;
+CREATE SEQUENCE t1;
+alter sequence t1 minvalue=100;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+alter sequence t1 minvalue=100 start=100 restart=100;
+rename table t1 to t2;
+select next value for t2;
+next value for t2
+100
+alter table t2 rename to t1;
+select next value for t1;
+next value for t1
+1100
+drop table t1;
diff --git a/mysql-test/suite/sql_sequence/aria.test b/mysql-test/suite/sql_sequence/aria.test
new file mode 100644
index 00000000000..8e8a50ef412
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/aria.test
@@ -0,0 +1,43 @@
+--source include/have_sequence.inc
+--source include/have_aria.inc
+
+#
+# Simple test of the aria engine
+# As most test is above the engine, we only have to test base functionality
+#
+
+set @@default_storage_engine="aria";
+
+CREATE SEQUENCE t1 cache=10;
+show create sequence t1;
+select NEXT VALUE for t1,seq from seq_1_to_20;
+select * from t1;
+drop sequence t1;
+
+#
+# Create and check
+#
+
+create sequence s1;
+check table s1;
+select next value for s1;
+flush tables;
+check table s1;
+select next value for s1;
+flush tables;
+repair table s1;
+select next value for s1;
+drop sequence s1;
+
+#
+# ALTER and RENAME
+
+CREATE SEQUENCE t1;
+--error ER_SEQUENCE_INVALID_DATA
+alter sequence t1 minvalue=100;
+alter sequence t1 minvalue=100 start=100 restart=100;
+rename table t1 to t2;
+select next value for t2;
+alter table t2 rename to t1;
+select next value for t1;
+drop table t1;
diff --git a/mysql-test/suite/sql_sequence/binlog.result b/mysql-test/suite/sql_sequence/binlog.result
new file mode 100644
index 00000000000..f01b3234e96
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/binlog.result
@@ -0,0 +1,33 @@
+create or replace sequence s1 cache 3;
+select next value for s1, minimum_value from s1 where maximum_value> 1;
+next value for s1 minimum_value
+1 1
+select next value for s1, minimum_value from s1 where maximum_value> 2;
+next value for s1 minimum_value
+2 1
+select next value for s1, minimum_value from s1 where maximum_value> 3;
+next value for s1 minimum_value
+3 1
+select next value for s1, minimum_value from s1 where maximum_value> 4;
+next value for s1 minimum_value
+4 1
+alter sequence s1 maxvalue 1000;
+drop sequence s1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; create or replace sequence s1 cache 3
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # select next value for s1, minimum_value from s1 where maximum_value> 1
+master-bin.000001 # Table_map # # table_id: # (test.s1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Annotate_rows # # select next value for s1, minimum_value from s1 where maximum_value> 4
+master-bin.000001 # Table_map # # table_id: # (test.s1)
+master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; alter sequence s1 maxvalue 1000
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP SEQUENCE `s1` /* generated by server */
diff --git a/mysql-test/suite/sql_sequence/binlog.test b/mysql-test/suite/sql_sequence/binlog.test
new file mode 100644
index 00000000000..5f2d52d7864
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/binlog.test
@@ -0,0 +1,27 @@
+--source include/have_udf.inc
+--source include/have_log_bin.inc
+--source include/binlog_start_pos.inc
+
+#
+# Testing binary logging of sequences
+#
+
+--disable_query_log
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+create or replace sequence s1 cache 3;
+select next value for s1, minimum_value from s1 where maximum_value> 1;
+select next value for s1, minimum_value from s1 where maximum_value> 2;
+select next value for s1, minimum_value from s1 where maximum_value> 3;
+select next value for s1, minimum_value from s1 where maximum_value> 4;
+
+#
+# Alter sequence
+#
+alter sequence s1 maxvalue 1000;
+
+drop sequence s1;
+
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result
new file mode 100644
index 00000000000..d7492f9a22b
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/create.result
@@ -0,0 +1,500 @@
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+create or replace sequence t1 engine=myisam;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+create or replace sequence t1 engine=innodb;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=InnoDB SEQUENCE=1
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+create or replace sequence t1 engine=maria;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=Aria
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=Aria SEQUENCE=1
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+create or replace sequence t1 engine=archive;
+ERROR HY000: Table storage engine 'ARCHIVE' does not support the create option 'SEQUENCE'
+show create table t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+create or replace sequence t1 start with 10;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 10 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+10 1 9223372036854775806 10 1 1000 0 0
+create or replace sequence t1 minvalue=11;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 11 minvalue 11 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 11 9223372036854775806 11 1 1000 0 0
+create or replace sequence t1 maxvalue=13 increment by -1;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 13 minvalue -9223372036854775807 maxvalue 13 increment by -1 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+13 -9223372036854775807 13 13 -1 1000 0 0
+create or replace sequence t1 increment by -1 cache 100;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with -1 minvalue -9223372036854775807 maxvalue -1 increment by -1 cache 100 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+-1 -9223372036854775807 -1 -1 -1 100 0 0
+create or replace sequence t1 cycle;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 cycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 1 0
+create or replace sequence t1 nocycle;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+create or replace sequence t1 cycle minvalue= 14;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 14 minvalue 14 maxvalue 9223372036854775806 increment by 1 cache 1000 cycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+14 14 9223372036854775806 14 1 1000 1 0
+create or replace sequence t1 cycle increment by -1;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with -1 minvalue -9223372036854775807 maxvalue -1 increment by -1 cache 1000 cycle ENGINE=MyISAM
+drop sequence t1;
+create sequence if not exists t1;
+create sequence if not exists t1 start with 10;
+Warnings:
+Note 1050 Table 't1' already exists
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+create or replace sequence t1 start with 10 minvalue=10 maxvalue=11 nocache cycle;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 10 minvalue 10 maxvalue 11 increment by 1 nocache cycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+10 10 11 10 1 0 1 0
+create or replace sequence t1 start with 10 minvalue=-10 maxvalue=11 cache=10 cycle increment by 10;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 10 minvalue -10 maxvalue 11 increment by 10 cache 10 cycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+10 -10 11 10 10 10 1 0
+create or replace sequence t1 start with 10 NO MAXVALUE NO MINVALUE;
+create or replace sequence t1 start with 10 maxvalue 10;
+create or replace sequence t1 start with 10 minvalue 10;
+create or replace sequence t1 start with 10 minvalue 10 maxvalue 11 cycle;
+create or replace sequence t1 start with 10 maxvalue=9223372036854775806;
+create or replace sequence t1 start with 10 minvalue=-9223372036854775807;
+drop sequence if exists t1;
+create sequence t1 increment by 0;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 0 cache 1000 nocycle ENGINE=MyISAM
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 0 1000 0 0
+drop sequence t1;
+create table t1 (a int);
+show create sequence t1;
+ERROR 42S02: 'test.t1' is not a SEQUENCE
+drop sequence t1;
+ERROR 42S02: 'test.t1' is not a SEQUENCE
+drop sequence if exists t1;
+Warnings:
+Note 4067 Unknown SEQUENCE: 'test.t1'
+create sequence t1 start with 10 maxvalue=9;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+create sequence t1 minvalue= 100 maxvalue=10;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+create sequence t1 start with 9 minvalue=10;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+create or replace sequence t1 maxvalue=13, increment by -1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' increment by -1' at line 1
+create or replace sequence t1 start with= 10 maxvalue=13;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '= 10 maxvalue=13' at line 1
+create or replace sequence t1 maxvalue=13, increment= -1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' increment= -1' at line 1
+create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NO MINVALUE' at line 1
+create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NO MINVALUE' at line 1
+create sequence t1 start with 10 maxvalue=9223372036854775807;
+ERROR HY000: Sequence 'test.t1' values are conflicting
+create sequence t1 start with 10 minvalue=-9223372036854775808;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '9223372036854775808' at line 1
+create sequence t1 RESTART WITH 10;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'RESTART' at line 1
+create or replace sequence t1 start with 10 NO MINVALUE minvalue=1;
+drop sequence t1;
+create sequence t1;
+show fields from t1;
+Field Type Null Key Default Extra
+next_not_cached_value bigint(21) NO NULL
+minimum_value bigint(21) NO NULL
+maximum_value bigint(21) NO NULL
+start_value bigint(21) NO NULL
+increment bigint(21) NO NULL
+cache_size bigint(21) unsigned NO NULL
+cycle_option tinyint(1) unsigned NO NULL
+cycle_count bigint(21) NO NULL
+flush tables;
+show fields from t1;
+Field Type Null Key Default Extra
+next_not_cached_value bigint(21) NO NULL
+minimum_value bigint(21) NO NULL
+maximum_value bigint(21) NO NULL
+start_value bigint(21) NO NULL
+increment bigint(21) NO NULL
+cache_size bigint(21) unsigned NO NULL
+cycle_option tinyint(1) unsigned NO NULL
+cycle_count bigint(21) NO NULL
+create or replace sequence t1 engine=aria;
+show fields from t1;
+Field Type Null Key Default Extra
+next_not_cached_value bigint(21) NO NULL
+minimum_value bigint(21) NO NULL
+maximum_value bigint(21) NO NULL
+start_value bigint(21) NO NULL
+increment bigint(21) NO NULL
+cache_size bigint(21) unsigned NO NULL
+cycle_option tinyint(1) unsigned NO NULL
+cycle_count bigint(21) NO NULL
+show fields from t1;
+Field Type Null Key Default Extra
+next_not_cached_value bigint(21) NO NULL
+minimum_value bigint(21) NO NULL
+maximum_value bigint(21) NO NULL
+start_value bigint(21) NO NULL
+increment bigint(21) NO NULL
+cache_size bigint(21) unsigned NO NULL
+cycle_option tinyint(1) unsigned NO NULL
+cycle_count bigint(21) NO NULL
+flush tables;
+create or replace sequence t1 comment= "test 1";
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM COMMENT='test 1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1 COMMENT='test 1'
+create or replace sequence t1 comment= "test 2" min_rows=1 max_rows=2;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM COMMENT='test 2'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM MIN_ROWS=1 MAX_ROWS=2 SEQUENCE=1 COMMENT='test 2'
+create or replace sequence t1 start=1 increment= 2;
+create or replace sequence t1 start 1 increment 2;
+create or replace sequence t1 cache +1;
+drop sequence t1;
+CREATE TABLE t1 (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) sequence=1;
+show create sequence t1;
+Table Create Table
+t1 CREATE SEQUENCE `t1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) ENGINE=MyISAM SEQUENCE=1
+drop sequence t1;
+CREATE OR REPLACE TABLE t1 (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count_not_exists` bigint(21) NOT NULL
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (cycle_count_not_exists)
+CREATE OR REPLACE TABLE t1 (
+`next_not_cached_value` int(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (next_not_cached_value)
+CREATE OR REPLACE TABLE t1 (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle` bigint(21) unsigned NOT NULL, /* error */
+`cycle_count` bigint(21) NOT NULL
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (cycle)
+CREATE OR REPLACE TABLE t1 (
+`next_not_cached_value` bigint(21), /* error */
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (next_not_cached_value)
+CREATE OR REPLACE TABLE t1 (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL,
+extra_field bigint(21)
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (Wrong number of columns)
+CREATE OR REPLACE TABLE t1 (
+`minimum_value` bigint(21) NOT NULL,
+`next_not_cached_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (minimum_value)
+CREATE OR REPLACE TABLE t1 (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL,
+key key1 (next_not_cached_value)
+) sequence=1;
+ERROR HY000: Sequence 'test.t1' table structure is invalid (Sequence tables cannot have any keys)
+drop sequence if exists t1;
+Warnings:
+Note 4067 Unknown SEQUENCE: 'test.t1'
+create sequence t1;
+create sequence t2;
+create table t3 (a int) engine=myisam;
+select table_catalog, table_schema, table_name, table_type from information_schema.tables where table_catalog="test";
+table_catalog table_schema table_name table_type
+CREATE SEQUENCE s1;
+drop sequence s1;
+drop sequence if exists t1,t2,t3,t4;
+Warnings:
+Note 4067 Unknown SEQUENCE: 'test.t3'
+Note 4067 Unknown SEQUENCE: 'test.t4'
+drop table if exists t1,t2,t3;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+Note 1051 Unknown table 'test.t2'
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop table t1,t2,s1;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop table if exists t1,t2,s1,s2;
+Warnings:
+Note 1051 Unknown table 'test.s2'
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop sequence t1,t2,s1,s2;
+ERROR 42S02: Unknown SEQUENCE: 'test.t1,test.t2,test.s2'
+drop table if exists t1,t2;
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop sequence if exists t1,t2,s1,s2;
+Warnings:
+Note 4067 Unknown SEQUENCE: 'test.t1'
+Note 4067 Unknown SEQUENCE: 'test.t2'
+Note 4067 Unknown SEQUENCE: 'test.s2'
+drop table if exists t1,t2;
+CREATE TEMPORARY SEQUENCE s1;
+DROP SEQUENCE s1;
+DROP TEMPORARY SEQUENCE s1;
+ERROR 42S02: Unknown SEQUENCE: 'test.s1'
+CREATE TEMPORARY SEQUENCE s1;
+CREATE SEQUENCE s2;
+CREATE TEMPORARY TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+DROP TEMPORARY SEQUENCE t1,t2,s1,s2;
+ERROR 42S02: Unknown SEQUENCE: 'test.t1,test.t2,test.s2'
+DROP TEMPORARY SEQUENCE s1;
+ERROR 42S02: Unknown SEQUENCE: 'test.s1'
+DROP TEMPORARY TABLE t1;
+DROP TABLE t1,t2,s1,s2;
+ERROR 42S02: Unknown table 'test.t1,test.s1'
+create view v1 as (select 1);
+CREATE SEQUENCE s1;
+DROP SEQUENCE s1,v1;
+ERROR 42S02: 'test.v1' is a view
+drop view v1;
+CREATE TEMPORARY SEQUENCE t1;
+select next value for t1;
+next value for t1
+1
+drop temporary table t1;
+select previous value for t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10;
+select next value for t1;
+next value for t1
+1
+select previous value for t1;
+previous value for t1
+1
+CREATE TEMPORARY SEQUENCE t1 start with 100 minvalue 100 maxvalue 200 increment by 1 cache 10;
+select previous value for t1;
+previous value for t1
+NULL
+select next value for t1;
+next value for t1
+100
+select previous value for t1;
+previous value for t1
+100
+drop temporary sequence t1;
+select previous value for t1;
+previous value for t1
+1
+drop sequence t1;
+CREATE TEMPORARY SEQUENCE t1 engine=innodb;
+select next value for t1;
+next value for t1
+1
+drop temporary table t1;
+select previous value for t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10 engine=innodb;
+select next value for t1;
+next value for t1
+1
+select previous value for t1;
+previous value for t1
+1
+CREATE TEMPORARY SEQUENCE t1 start with 100 minvalue 100 maxvalue 200 increment by 1 cache 10 engine=innodb;
+select previous value for t1;
+previous value for t1
+NULL
+select next value for t1;
+next value for t1
+100
+select previous value for t1;
+previous value for t1
+100
+drop temporary sequence t1;
+select previous value for t1;
+previous value for t1
+1
+drop sequence t1;
+create table t1 (a int) engine=sql_sequence;
+ERROR 42000: Unknown storage engine 'sql_sequence'
diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test
new file mode 100644
index 00000000000..23c32939efc
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/create.test
@@ -0,0 +1,377 @@
+#
+# Test create options with sequences
+#
+--source include/have_innodb.inc
+--source include/have_archive.inc
+
+drop table if exists t1;
+
+#
+# Check some sample engines
+#
+
+create or replace sequence t1 engine=myisam;
+show create sequence t1;
+show create table t1;
+select * from t1;
+create or replace sequence t1 engine=innodb;
+show create sequence t1;
+show create table t1;
+select * from t1;
+create or replace sequence t1 engine=maria;
+show create sequence t1;
+show create table t1;
+select * from t1;
+--error ER_ILLEGAL_HA_CREATE_OPTION
+create or replace sequence t1 engine=archive;
+#
+# The following error should be fixed. We shouldn't delete old table on errors
+#
+--error ER_NO_SUCH_TABLE
+show create table t1;
+
+
+# Check start values
+create or replace sequence t1 start with 10;
+show create sequence t1;
+select * from t1;
+create or replace sequence t1 minvalue=11;
+show create sequence t1;
+select * from t1;
+create or replace sequence t1 maxvalue=13 increment by -1;
+show create sequence t1;
+select * from t1;
+
+create or replace sequence t1 increment by -1 cache 100;
+show create sequence t1;
+select * from t1;
+create or replace sequence t1 cycle;
+show create sequence t1;
+select * from t1;
+create or replace sequence t1 nocycle;
+show create sequence t1;
+select * from t1;
+show create sequence t1;
+create or replace sequence t1 cycle minvalue= 14;
+show create sequence t1;
+select * from t1;
+create or replace sequence t1 cycle increment by -1;
+show create sequence t1;
+
+drop sequence t1;
+create sequence if not exists t1;
+create sequence if not exists t1 start with 10;
+select * from t1;
+show create sequence t1;
+
+create or replace sequence t1 start with 10 minvalue=10 maxvalue=11 nocache cycle;
+show create sequence t1;
+select * from t1;
+create or replace sequence t1 start with 10 minvalue=-10 maxvalue=11 cache=10 cycle increment by 10;
+show create sequence t1;
+select * from t1;
+
+# NO MINVALUE, NO MAXVALUE
+create or replace sequence t1 start with 10 NO MAXVALUE NO MINVALUE;
+
+# Some edge cases
+create or replace sequence t1 start with 10 maxvalue 10;
+create or replace sequence t1 start with 10 minvalue 10;
+create or replace sequence t1 start with 10 minvalue 10 maxvalue 11 cycle;
+create or replace sequence t1 start with 10 maxvalue=9223372036854775806;
+create or replace sequence t1 start with 10 minvalue=-9223372036854775807;
+drop sequence if exists t1;
+
+create sequence t1 increment by 0;
+show create sequence t1;
+select * from t1;
+drop sequence t1;
+
+#
+# Wrong usage and arguments to create sequence
+#
+
+create table t1 (a int);
+--error ER_NOT_SEQUENCE
+show create sequence t1;
+--error ER_NOT_SEQUENCE2
+drop sequence t1;
+drop sequence if exists t1;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence t1 start with 10 maxvalue=9;
+--error ER_SEQUENCE_INVALID_DATA
+create sequence t1 minvalue= 100 maxvalue=10;
+--error ER_SEQUENCE_INVALID_DATA
+create sequence t1 start with 9 minvalue=10;
+--error ER_PARSE_ERROR
+create or replace sequence t1 maxvalue=13, increment by -1;
+--error ER_PARSE_ERROR
+create or replace sequence t1 start with= 10 maxvalue=13;
+--error ER_PARSE_ERROR
+create or replace sequence t1 maxvalue=13, increment= -1;
+--error ER_PARSE_ERROR
+create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
+--error ER_PARSE_ERROR
+create or replace sequence t1 start with 10 min_value=1 NO MINVALUE;
+--error ER_SEQUENCE_INVALID_DATA
+create sequence t1 start with 10 maxvalue=9223372036854775807;
+--error ER_PARSE_ERROR
+create sequence t1 start with 10 minvalue=-9223372036854775808;
+--error ER_PARSE_ERROR
+create sequence t1 RESTART WITH 10;
+
+# This should probably give an error
+create or replace sequence t1 start with 10 NO MINVALUE minvalue=1;
+drop sequence t1;
+
+#
+# Test with LIST COLUMNS as first command
+#
+create sequence t1;
+show fields from t1;
+flush tables;
+show fields from t1;
+create or replace sequence t1 engine=aria;
+show fields from t1;
+show fields from t1;
+flush tables;
+
+#
+# Test with other create options
+#
+
+create or replace sequence t1 comment= "test 1";
+show create sequence t1;
+show create table t1;
+create or replace sequence t1 comment= "test 2" min_rows=1 max_rows=2;
+show create sequence t1;
+show create table t1;
+create or replace sequence t1 start=1 increment= 2;
+create or replace sequence t1 start 1 increment 2;
+create or replace sequence t1 cache +1;
+drop sequence t1;
+
+#
+# test with create table
+#
+
+CREATE TABLE t1 (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) sequence=1;
+
+show create sequence t1;
+show create table t1;
+drop sequence t1;
+
+# Wrong column name
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count_not_exists` bigint(21) NOT NULL
+) sequence=1;
+
+# Wrong type
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `next_not_cached_value` int(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) sequence=1;
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle` bigint(21) unsigned NOT NULL, /* error */
+ `cycle_count` bigint(21) NOT NULL
+) sequence=1;
+
+
+# Missing NOT NULL
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `next_not_cached_value` bigint(21), /* error */
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) sequence=1;
+
+# Extra field
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL,
+ extra_field bigint(21)
+) sequence=1;
+
+# Wrong field order
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `minimum_value` bigint(21) NOT NULL,
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) sequence=1;
+
+# key
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+CREATE OR REPLACE TABLE t1 (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL,
+ key key1 (next_not_cached_value)
+) sequence=1;
+
+drop sequence if exists t1;
+
+#
+# DROP SEQUENCE
+#
+
+create sequence t1;
+create sequence t2;
+create table t3 (a int) engine=myisam;
+select table_catalog, table_schema, table_name, table_type from information_schema.tables where table_catalog="test";
+
+CREATE SEQUENCE s1;
+drop sequence s1;
+
+drop sequence if exists t1,t2,t3,t4;
+drop table if exists t1,t2,t3;
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop table t1,t2,s1;
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop table if exists t1,t2,s1,s2;
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+--error ER_UNKNOWN_SEQUENCES
+drop sequence t1,t2,s1,s2;
+drop table if exists t1,t2;
+
+CREATE TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+CREATE SEQUENCE s1;
+drop sequence if exists t1,t2,s1,s2;
+drop table if exists t1,t2;
+
+CREATE TEMPORARY SEQUENCE s1;
+DROP SEQUENCE s1;
+--error ER_UNKNOWN_SEQUENCES
+DROP TEMPORARY SEQUENCE s1;
+
+CREATE TEMPORARY SEQUENCE s1;
+CREATE SEQUENCE s2;
+CREATE TEMPORARY TABLE t1 (a int);
+CREATE TABLE t2 (a int);
+--error ER_UNKNOWN_SEQUENCES
+DROP TEMPORARY SEQUENCE t1,t2,s1,s2;
+--error ER_UNKNOWN_SEQUENCES
+DROP TEMPORARY SEQUENCE s1;
+DROP TEMPORARY TABLE t1;
+--error ER_BAD_TABLE_ERROR
+DROP TABLE t1,t2,s1,s2;
+
+create view v1 as (select 1);
+CREATE SEQUENCE s1;
+--error ER_IT_IS_A_VIEW
+DROP SEQUENCE s1,v1;
+drop view v1;
+
+#
+# CREATE TEMPORARY SEQUENCE
+#
+
+CREATE TEMPORARY SEQUENCE t1;
+select next value for t1;
+drop temporary table t1;
+--error ER_NO_SUCH_TABLE
+select previous value for t1;
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10;
+select next value for t1;
+select previous value for t1;
+CREATE TEMPORARY SEQUENCE t1 start with 100 minvalue 100 maxvalue 200 increment by 1 cache 10;
+select previous value for t1;
+select next value for t1;
+select previous value for t1;
+drop temporary sequence t1;
+select previous value for t1;
+drop sequence t1;
+
+CREATE TEMPORARY SEQUENCE t1 engine=innodb;
+select next value for t1;
+drop temporary table t1;
+--error ER_NO_SUCH_TABLE
+select previous value for t1;
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 10 engine=innodb;
+select next value for t1;
+select previous value for t1;
+CREATE TEMPORARY SEQUENCE t1 start with 100 minvalue 100 maxvalue 200 increment by 1 cache 10 engine=innodb;
+select previous value for t1;
+select next value for t1;
+select previous value for t1;
+drop temporary sequence t1;
+select previous value for t1;
+drop sequence t1;
+
+#
+# Check that we can't create anything with the sequence engine
+#
+
+--error ER_UNKNOWN_STORAGE_ENGINE
+create table t1 (a int) engine=sql_sequence;
diff --git a/mysql-test/suite/sql_sequence/disabled.def b/mysql-test/suite/sql_sequence/disabled.def
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/disabled.def
diff --git a/mysql-test/suite/sql_sequence/gtid-master.opt b/mysql-test/suite/sql_sequence/gtid-master.opt
new file mode 100644
index 00000000000..dd4fb8c5f9a
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/gtid-master.opt
@@ -0,0 +1,3 @@
+--binlog_format=row
+--query_cache_type=1
+--log-slave-updates
diff --git a/mysql-test/suite/sql_sequence/gtid-slave.opt b/mysql-test/suite/sql_sequence/gtid-slave.opt
new file mode 100644
index 00000000000..dc0ff1864e0
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/gtid-slave.opt
@@ -0,0 +1,4 @@
+--binlog_format=row
+--query_cache_type=1
+--read_only=true
+--log-slave-updates
diff --git a/mysql-test/suite/sql_sequence/gtid.result b/mysql-test/suite/sql_sequence/gtid.result
new file mode 100644
index 00000000000..4c0a4e0e8fc
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/gtid.result
@@ -0,0 +1,829 @@
+include/master-slave.inc
+[connection master]
+connection master;
+create database s_db;
+grant all on s_db.* to normal_1@'%' identified by 'pass';
+grant all on test.* to normal_2@'%' identified by 'pass';
+grant all on s_db.* to normal_3@'%' identified by 'pass';
+grant all on test.* to normal_4@'%' identified by 'pass';
+grant select on test.* to normal_5@'%' identified by 'pass';
+connection slave;
+connect m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT;
+connect m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT;
+connect m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT;
+connect s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT;
+connect s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT;
+connection slave;
+set global read_only=on;
+###########################################
+master and slave sync sequence.
+###########################################
+connection master;
+use s_db;
+create sequence s1;
+show create table s1;
+Table Create Table
+s1 CREATE TABLE `s1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1
+connection slave;
+use s_db;
+show create table s1;
+Table Create Table
+s1 CREATE TABLE `s1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1
+connection master;
+use s_db;
+drop sequence s1;
+###########################################
+not support create table engine=sequence.
+###########################################
+connection master;
+create table t(id int)engine=sequence;
+ERROR 42000: Unknown storage engine 'sequence'
+create table t(id int)engine=innodb;
+alter table t engine=sequence;
+ERROR 42000: Unknown storage engine 'sequence'
+drop table t;
+###########################################
+not support alter sequence table.
+###########################################
+connection master;
+create sequence s2;
+alter table s2 add id int;
+ERROR HY000: Sequence 's_db.s2' table structure is invalid (Wrong number of columns)
+alter table s2 add index ind_x(start);
+ERROR HY000: Sequence 's_db.s2' table structure is invalid (Sequence tables cannot have any keys)
+drop sequence s2;
+###########################################
+Support create temporary sequence.
+###########################################
+connection master;
+create temporary sequence s2;
+drop temporary sequence s2;
+###########################################
+all invalid sequence value
+###########################################
+connection master;
+use s_db;
+create sequence s2 start with 1
+minvalue 1
+maxvalue 100000
+increment by 1
+cache 10000
+cycle;
+drop sequence s2;
+create sequence s2 start with 1
+minvalue 1
+maxvalue 100000
+increment by 1
+cache 10000
+nocycle;
+drop sequence s2;
+create sequence s2 start with 1
+minvalue 1
+maxvalue 100000
+increment by 1
+nocache
+nocycle;
+drop sequence s2;
+create sequence s2 start with 1
+minvalue 5
+maxvalue 100000
+increment by 1
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+create sequence s2 start with 1
+minvalue 5
+maxvalue 5
+increment by 1
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+create sequence s2 start with 1
+minvalue 5
+maxvalue 4
+increment by 1
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+create sequence s2 start with 1
+minvalue 5
+maxvalue 4
+increment by 0
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+###########################################
+global read lock prevent query sequence
+###########################################
+connection master;
+use s_db;
+create sequence s_db.s1;
+flush table with read lock;
+select next value for s1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop sequence s_db.s1;
+###########################################
+query cache test
+###########################################
+connection master;
+use s_db;
+show global variables like 'query_cache_type';
+Variable_name Value
+query_cache_type ON
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 0
+show status like 'Qcache_inserts';
+Variable_name Value
+Qcache_inserts 0
+###########################################
+priv test
+###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+select * from s_db.s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+select next value for s_db.s1;
+next value for s_db.s1
+1
+select * from s_db.s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1001 1 9223372036854775806 1 1 1000 0 0
+create sequence s_db.s2;
+drop sequence s_db.s2;
+connection m_normal_2;
+select next value for s_db.s1;
+ERROR 42000: INSERT command denied to user 'normal_2'@'localhost' for table 's1'
+create sequence s_db.s2;
+ERROR 42000: CREATE command denied to user 'normal_2'@'localhost' for table 's2'
+connection m_normal_1;
+drop sequence s_db.s1;
+###########################################
+run out sequence value
+###########################################
+connection m_normal_1;
+use s_db;
+create sequence s_t start with 1 cache 2 maxvalue 5;
+create table t(id int);
+insert into t values(1111);
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+ERROR HY000: Sequence 's_db.s_t' has run out
+insert into t select next value for s_t;
+ERROR HY000: Sequence 's_db.s_t' has run out
+commit;
+select * from t;
+id
+1111
+1
+2
+3
+4
+5
+connection master;
+connection slave;
+connection s_normal_3;
+use s_db;
+select * from t;
+id
+1111
+1
+2
+3
+4
+5
+connection m_normal_1;
+use s_db;
+drop sequence s_t;
+drop table t;
+###########################################
+read_only prevent query sequence
+###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+show global variables like 'read_only';
+Variable_name Value
+read_only OFF
+select next value for s_db.s1;
+next value for s_db.s1
+1
+connection s_normal_3;
+show global variables like 'read_only';
+Variable_name Value
+read_only ON
+select next value for s_db.s1;
+ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
+connection m_normal_1;
+drop sequence s_db.s1;
+###########################################
+update based table
+###########################################
+connection m_normal_1;
+use s_db;
+create sequence s_t start with 1 minvalue 1 maxvalue 20 increment by 1 cache 5 cycle;
+connection master;
+connection slave;
+connection s_normal_3;
+use s_db;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 20 1 1 5 1 0
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+1
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+6 1 20 1 1 5 1 0
+connection master;
+connection slave;
+connection s_normal_3;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+6 1 20 1 1 5 1 0
+------------------------------------------
+master update nextval;
+------------------------------------------
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+2
+update s_t set next_not_cached_value= 11;
+ERROR HY000: Storage engine SEQUENCE of the table `s_db`.`s_t` doesn't have this option
+alter sequence s_t restart=11;
+commit;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 20 1 1 5 1 0
+connection master;
+connection slave;
+------------------------------------------
+show slave nextval;
+------------------------------------------
+connection s_normal_3;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 20 1 1 5 1 0
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+11
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+connection master;
+connection slave;
+connection s_normal_3;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+------------------------------------------
+update into invalid sequence
+------------------------------------------
+connection m_normal_1;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+update s_t set next_not_cached_value= 11,start_value=10, minimum_value=11;
+ERROR HY000: Storage engine SEQUENCE of the table `s_db`.`s_t` doesn't have this option
+ALTER SEQUENCE s_t restart with 11 start=10 minvalue=11;
+ERROR HY000: Sequence 's_db.s_t' values are conflicting
+commit;
+create table t_1(id int);
+insert into t_1 value(1111);
+select next value for s_t;
+next value for s_t
+12
+insert into t_1 select next value for s_t;
+commit;
+select * from t_1;
+id
+1111
+13
+------------------------------------------
+delete sequence row
+------------------------------------------
+connection m_normal_1;
+delete from s_t;
+ERROR HY000: Storage engine SEQUENCE of the table `s_db`.`s_t` doesn't have this option
+commit;
+select next value for s_t;
+next value for s_t
+14
+connection m_normal_1;
+drop sequence s_t;
+drop table t_1;
+###########################################
+test transaction context (innodb)
+###########################################
+------------------------------------------
+transaction table and sequence
+normal transaction commit
+------------------------------------------
+connection m_normal_1;
+use s_db;
+create sequence s_1 cache 5;
+create table t_1(id int)engine=innodb;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+select * from t_1;
+id
+1111
+1
+2
+2222
+connection master;
+connection slave;
+connection s_normal_3;
+use s_db;
+select * from t_1;
+id
+1111
+1
+2
+2222
+------------------------------------------
+normal transaction rollback
+------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+rollback;
+select * from t_1;
+id
+1111
+1
+2
+2222
+select next value for s_1;
+next value for s_1
+11
+connection master;
+connection slave;
+connection s_normal_3;
+use s_db;
+select * from t_1;
+id
+1111
+1
+2
+2222
+connection m_normal_1;
+use s_db;
+drop sequence s_1;
+drop table t_1;
+###########################################
+test transaction context (myisam)
+###########################################
+------------------------------------------
+transaction table and sequence
+normal transaction commit
+------------------------------------------
+connection m_normal_1;
+use s_db;
+create sequence s_1 cache 5;
+create table t_1(id int)engine=myisam;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+select * from t_1;
+id
+1111
+1
+2
+2222
+connection master;
+connection slave;
+connection s_normal_3;
+use s_db;
+select * from t_1;
+id
+1111
+1
+2
+2222
+------------------------------------------
+normal transaction rollback
+------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+rollback;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+select next value for s_1;
+next value for s_1
+11
+connection master;
+connection slave;
+connection s_normal_3;
+use s_db;
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+connection m_normal_1;
+use s_db;
+drop sequence s_1;
+drop table t_1;
+###########################################
+close binlog
+###########################################
+connection m_normal_1;
+use s_db;
+create sequence s1 cache 2;
+select next value for s1;
+next value for s1
+1
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+next value for s1
+3
+select next value for s1;
+next value for s1
+4
+commit;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 9223372036854775806 1 1 2 0 0
+connection master;
+connection slave;
+connection slave;
+use s_db;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 9223372036854775806 1 1 2 0 0
+------------------------------------------
+close session binlog.
+------------------------------------------
+connection master;
+set session sql_log_bin=off;
+select next value for s1;
+next value for s1
+5
+select next value for s1;
+next value for s1
+6
+select next value for s1;
+next value for s1
+7
+select next value for s1;
+next value for s1
+8
+set session sql_log_bin=on;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+9 1 9223372036854775806 1 1 2 0 0
+connection master;
+connection slave;
+connection slave;
+use s_db;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 9223372036854775806 1 1 2 0 0
+connection m_normal_1;
+use s_db;
+drop sequence s1;
+###########################################
+statement binlog
+###########################################
+------------------------------------------
+set binlog_format=statement
+------------------------------------------
+connection master;
+set session binlog_format=statement;
+show session variables like '%binlog_format%';
+Variable_name Value
+binlog_format STATEMENT
+wsrep_forced_binlog_format NONE
+create sequence s1 cache 2;
+select next value for s1;
+ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.
+set session binlog_format=row;
+select next value for s1;
+next value for s1
+1
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 1 9223372036854775806 1 1 2 0 0
+connection master;
+connection slave;
+use s_db;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 1 9223372036854775806 1 1 2 0 0
+connection m_normal_1;
+use s_db;
+drop sequence s1;
+###########################################
+test savepoint
+###########################################
+connection master;
+set session binlog_format=row;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+begin;
+insert into t1 values(1111);
+savepoint sp1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+insert into t1 values(2222);
+select * from t1;
+id
+1111
+1
+2
+3
+2222
+rollback to sp1;
+select * from t1;
+id
+1111
+select next value for s1;
+next value for s1
+4
+commit;
+drop sequence s1;
+drop table t1;
+###########################################
+test proc
+###########################################
+connection m_normal_1;
+use s_db;
+create table t(id int)engine=innodb;
+create procedure p1()
+begin
+create sequence s1 cache 2;
+end//
+create procedure p2()
+begin
+insert into t select next value for s1;
+commit;
+end//
+call p1();
+call p2();
+call p2();
+call p2();
+call p2();
+select * from t;
+id
+1
+2
+3
+4
+connection master;
+connection slave;
+use s_db;
+select * from t;
+id
+1
+2
+3
+4
+connection m_normal_1;
+drop table t;
+drop sequence s1;
+drop procedure p1;
+drop procedure p2;
+###########################################
+test trigger
+###########################################
+connection m_normal_1;
+use s_db;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+create table t2(id int)engine=innodb;
+CREATE TRIGGER tri_1
+before INSERT ON t2 FOR EACH ROW
+BEGIN
+INSERT INTO t1 select next value for s1;
+END//
+begin;
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+select * from t2;
+id
+1111
+1111
+1111
+1111
+select * from t1;
+id
+1
+2
+3
+4
+rollback;
+select * from t2;
+id
+select * from t1;
+id
+select next value for s1;
+next value for s1
+5
+drop trigger tri_1;
+drop table t1;
+drop table t2;
+drop sequence s1;
+###########################################
+test function
+###########################################
+connection m_normal_1;
+use s_db;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+CREATE function f1() returns int
+BEGIN
+INSERT INTO t1 select next value for s1;
+return (1);
+END//
+begin;
+select f1();
+f1()
+1
+select f1();
+f1()
+1
+select f1();
+f1()
+1
+select f1();
+f1()
+1
+select * from t1;
+id
+1
+2
+3
+4
+rollback;
+select * from t1;
+id
+select next value for s1;
+next value for s1
+5
+drop function f1;
+drop table t1;
+drop sequence s1;
+##############
+Test GRANT
+##############
+connection m_normal_2;
+create table t1 (a int);
+create sequence s1;
+select next value for s1;
+next value for s1
+1
+insert into t1 values (1);
+connection m_normal_3;
+select * from t1;
+a
+1
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1001 1 9223372036854775806 1 1 1000 0 0
+select previous value for s1;
+previous value for s1
+NULL
+insert into t1 values (2);
+ERROR 42000: INSERT command denied to user 'normal_5'@'localhost' for table 't1'
+select next value for s1;
+ERROR 42000: INSERT command denied to user 'normal_5'@'localhost' for table 's1'
+do setval(s1,1000,0);
+ERROR 42000: INSERT command denied to user 'normal_5'@'localhost' for table 's1'
+connection master;
+grant insert on test.* to normal_5@'%' identified by 'pass';
+disconnect m_normal_3;
+connect m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT;
+insert into t1 values (2);
+select t1.*, (next value for s1) from t1;
+a (next value for s1)
+1 2
+2 3
+do setval(s1,10000,0);
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+10000 1 9223372036854775806 1 1 1000 0 0
+connection m_normal_2;
+drop table t1;
+drop sequence s1;
+#
+# Cleanup
+#
+connection master;
+use s_db;
+drop database s_db;
+drop user normal_1@'%';
+drop user normal_2@'%';
+drop user normal_3@'%';
+drop user normal_4@'%';
+drop user normal_5@'%';
+include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/gtid.test b/mysql-test/suite/sql_sequence/gtid.test
new file mode 100644
index 00000000000..a354062a05c
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/gtid.test
@@ -0,0 +1,704 @@
+#
+# This test is based on tests from ALISQL test suite
+#
+
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--source include/have_innodb.inc
+
+connection master;
+create database s_db;
+grant all on s_db.* to normal_1@'%' identified by 'pass';
+grant all on test.* to normal_2@'%' identified by 'pass';
+grant all on s_db.* to normal_3@'%' identified by 'pass';
+grant all on test.* to normal_4@'%' identified by 'pass';
+grant select on test.* to normal_5@'%' identified by 'pass';
+
+--sync_slave_with_master
+
+connect(m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT);
+connect(m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT);
+connect(m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT);
+
+connect(s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT);
+connect(s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT);
+
+connection slave;
+set global read_only=on;
+
+--echo ###########################################
+--echo master and slave sync sequence.
+--echo ###########################################
+connection master;
+use s_db;
+
+create sequence s1;
+show create table s1;
+
+--sync_slave_with_master
+use s_db;
+show create table s1;
+
+connection master;
+use s_db;
+
+drop sequence s1;
+
+--echo ###########################################
+--echo not support create table engine=sequence.
+--echo ###########################################
+connection master;
+
+--error ER_UNKNOWN_STORAGE_ENGINE
+create table t(id int)engine=sequence;
+
+create table t(id int)engine=innodb;
+
+--error ER_UNKNOWN_STORAGE_ENGINE
+alter table t engine=sequence;
+
+drop table t;
+--echo ###########################################
+--echo not support alter sequence table.
+--echo ###########################################
+connection master;
+
+create sequence s2;
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+alter table s2 add id int;
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+alter table s2 add index ind_x(start);
+drop sequence s2;
+
+--echo ###########################################
+--echo Support create temporary sequence.
+--echo ###########################################
+connection master;
+
+create temporary sequence s2;
+drop temporary sequence s2;
+
+--echo ###########################################
+--echo all invalid sequence value
+--echo ###########################################
+
+connection master;
+use s_db;
+create sequence s2 start with 1
+ minvalue 1
+ maxvalue 100000
+ increment by 1
+ cache 10000
+ cycle;
+drop sequence s2;
+create sequence s2 start with 1
+ minvalue 1
+ maxvalue 100000
+ increment by 1
+ cache 10000
+ nocycle;
+drop sequence s2;
+create sequence s2 start with 1
+ minvalue 1
+ maxvalue 100000
+ increment by 1
+ nocache
+ nocycle;
+drop sequence s2;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 100000
+ increment by 1
+ nocache
+ nocycle;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 5
+ increment by 1
+ nocache
+ nocycle;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 4
+ increment by 1
+ nocache
+ nocycle;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 4
+ increment by 0
+ nocache
+ nocycle;
+
+--echo ###########################################
+--echo global read lock prevent query sequence
+--echo ###########################################
+connection master;
+use s_db;
+create sequence s_db.s1;
+flush table with read lock;
+--error ER_CANT_UPDATE_WITH_READLOCK
+select next value for s1;
+
+unlock tables;
+
+drop sequence s_db.s1;
+
+--echo ###########################################
+--echo query cache test
+--echo ###########################################
+connection master;
+use s_db;
+show global variables like 'query_cache_type';
+
+show status like 'Qcache_hits';
+show status like 'Qcache_inserts';
+
+--echo ###########################################
+--echo priv test
+--echo ###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+select * from s_db.s1;
+select next value for s_db.s1;
+select * from s_db.s1;
+create sequence s_db.s2;
+drop sequence s_db.s2;
+
+
+connection m_normal_2;
+--error ER_TABLEACCESS_DENIED_ERROR
+select next value for s_db.s1;
+--error ER_TABLEACCESS_DENIED_ERROR
+create sequence s_db.s2;
+
+connection m_normal_1;
+drop sequence s_db.s1;
+
+--echo ###########################################
+--echo run out sequence value
+--echo ###########################################
+connection m_normal_1;
+use s_db;
+create sequence s_t start with 1 cache 2 maxvalue 5;
+create table t(id int);
+insert into t values(1111);
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+--error ER_SEQUENCE_RUN_OUT
+insert into t select next value for s_t;
+--error ER_SEQUENCE_RUN_OUT
+insert into t select next value for s_t;
+commit;
+select * from t;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+use s_db;
+select * from t;
+
+connection m_normal_1;
+use s_db;
+drop sequence s_t;
+drop table t;
+
+--echo ###########################################
+--echo read_only prevent query sequence
+--echo ###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+show global variables like 'read_only';
+select next value for s_db.s1;
+
+connection s_normal_3;
+show global variables like 'read_only';
+--error ER_OPTION_PREVENTS_STATEMENT
+select next value for s_db.s1;
+
+connection m_normal_1;
+drop sequence s_db.s1;
+
+--echo ###########################################
+--echo update based table
+--echo ###########################################
+connection m_normal_1;
+use s_db;
+create sequence s_t start with 1 minvalue 1 maxvalue 20 increment by 1 cache 5 cycle;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+use s_db;
+select * from s_t;
+
+connection m_normal_1;
+select next value for s_t;
+select * from s_t;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from s_t;
+
+--echo ------------------------------------------
+--echo master update nextval;
+--echo ------------------------------------------
+connection m_normal_1;
+select next value for s_t;
+--error ER_ILLEGAL_HA
+update s_t set next_not_cached_value= 11;
+alter sequence s_t restart=11;
+commit;
+
+select * from s_t;
+
+connection master;
+--sync_slave_with_master
+
+--echo ------------------------------------------
+--echo show slave nextval;
+--echo ------------------------------------------
+connection s_normal_3;
+select * from s_t;
+
+connection m_normal_1;
+select next value for s_t;
+select * from s_t;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from s_t;
+
+
+--echo ------------------------------------------
+--echo update into invalid sequence
+--echo ------------------------------------------
+connection m_normal_1;
+select * from s_t;
+--error ER_ILLEGAL_HA
+update s_t set next_not_cached_value= 11,start_value=10, minimum_value=11;
+--error ER_SEQUENCE_INVALID_DATA
+ALTER SEQUENCE s_t restart with 11 start=10 minvalue=11;
+commit;
+
+create table t_1(id int);
+insert into t_1 value(1111);
+select next value for s_t;
+insert into t_1 select next value for s_t;
+commit;
+
+select * from t_1;
+
+--echo ------------------------------------------
+--echo delete sequence row
+--echo ------------------------------------------
+connection m_normal_1;
+--error ER_ILLEGAL_HA
+delete from s_t;
+commit;
+
+select next value for s_t;
+
+connection m_normal_1;
+drop sequence s_t;
+drop table t_1;
+
+--echo ###########################################
+--echo test transaction context (innodb)
+--echo ###########################################
+
+--echo ------------------------------------------
+--echo transaction table and sequence
+--echo normal transaction commit
+--echo ------------------------------------------
+connection m_normal_1;
+use s_db;
+create sequence s_1 cache 5;
+
+create table t_1(id int)engine=innodb;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+
+select * from t_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+use s_db;
+select * from t_1;
+
+--echo ------------------------------------------
+--echo normal transaction rollback
+--echo ------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+
+select * from t_1;
+rollback;
+
+select * from t_1;
+select next value for s_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+use s_db;
+select * from t_1;
+
+connection m_normal_1;
+use s_db;
+drop sequence s_1;
+drop table t_1;
+
+--echo ###########################################
+--echo test transaction context (myisam)
+--echo ###########################################
+
+--echo ------------------------------------------
+--echo transaction table and sequence
+--echo normal transaction commit
+--echo ------------------------------------------
+connection m_normal_1;
+use s_db;
+create sequence s_1 cache 5;
+
+create table t_1(id int)engine=myisam;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+
+select * from t_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+use s_db;
+select * from t_1;
+
+--echo ------------------------------------------
+--echo normal transaction rollback
+--echo ------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+
+select * from t_1;
+rollback;
+
+select * from t_1;
+select next value for s_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+use s_db;
+select * from t_1;
+
+connection m_normal_1;
+use s_db;
+drop sequence s_1;
+drop table t_1;
+
+--echo ###########################################
+--echo close binlog
+--echo ###########################################
+connection m_normal_1;
+use s_db;
+create sequence s1 cache 2;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+
+commit;
+select * from s1;
+
+connection master;
+--sync_slave_with_master
+
+connection slave;
+use s_db;
+select * from s1;
+
+--echo ------------------------------------------
+--echo close session binlog.
+--echo ------------------------------------------
+connection master;
+set session sql_log_bin=off;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+
+set session sql_log_bin=on;
+select * from s1;
+
+connection master;
+--sync_slave_with_master
+
+connection slave;
+use s_db;
+select * from s1;
+
+connection m_normal_1;
+use s_db;
+drop sequence s1;
+
+--echo ###########################################
+--echo statement binlog
+--echo ###########################################
+--echo ------------------------------------------
+--echo set binlog_format=statement
+--echo ------------------------------------------
+connection master;
+set session binlog_format=statement;
+show session variables like '%binlog_format%';
+create sequence s1 cache 2;
+--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+select next value for s1;
+
+set session binlog_format=row;
+select next value for s1;
+select * from s1;
+
+connection master;
+--sync_slave_with_master
+
+use s_db;
+select * from s1;
+
+connection m_normal_1;
+use s_db;
+drop sequence s1;
+
+--echo ###########################################
+--echo test savepoint
+--echo ###########################################
+connection master;
+set session binlog_format=row;
+
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+
+begin;
+insert into t1 values(1111);
+savepoint sp1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+
+insert into t1 values(2222);
+
+select * from t1;
+rollback to sp1;
+select * from t1;
+select next value for s1;
+
+commit;
+
+drop sequence s1;
+drop table t1;
+
+--echo ###########################################
+--echo test proc
+--echo ###########################################
+connection m_normal_1;
+use s_db;
+create table t(id int)engine=innodb;
+
+delimiter //;
+
+create procedure p1()
+begin
+ create sequence s1 cache 2;
+end//
+
+create procedure p2()
+begin
+ insert into t select next value for s1;
+ commit;
+end//
+
+delimiter ;//
+
+call p1();
+call p2();
+call p2();
+call p2();
+call p2();
+
+select * from t;
+
+connection master;
+--sync_slave_with_master
+
+use s_db;
+select * from t;
+
+connection m_normal_1;
+drop table t;
+drop sequence s1;
+drop procedure p1;
+drop procedure p2;
+
+--echo ###########################################
+--echo test trigger
+--echo ###########################################
+connection m_normal_1;
+use s_db;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+create table t2(id int)engine=innodb;
+
+delimiter //;
+CREATE TRIGGER tri_1
+ before INSERT ON t2 FOR EACH ROW
+BEGIN
+ INSERT INTO t1 select next value for s1;
+END//
+delimiter ;//
+
+begin;
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+
+select * from t2;
+select * from t1;
+rollback;
+select * from t2;
+select * from t1;
+
+select next value for s1;
+
+
+drop trigger tri_1;
+drop table t1;
+drop table t2;
+drop sequence s1;
+
+--echo ###########################################
+--echo test function
+--echo ###########################################
+connection m_normal_1;
+use s_db;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+
+delimiter //;
+CREATE function f1() returns int
+BEGIN
+ INSERT INTO t1 select next value for s1;
+ return (1);
+END//
+delimiter ;//
+
+begin;
+select f1();
+select f1();
+select f1();
+select f1();
+
+select * from t1;
+rollback;
+select * from t1;
+
+select next value for s1;
+
+drop function f1;
+drop table t1;
+drop sequence s1;
+
+--echo ##############
+--echo Test GRANT
+--echo ##############
+
+connection m_normal_2;
+create table t1 (a int);
+create sequence s1;
+select next value for s1;
+insert into t1 values (1);
+connection m_normal_3;
+select * from t1;
+select * from s1;
+select previous value for s1;
+--error ER_TABLEACCESS_DENIED_ERROR
+insert into t1 values (2);
+--error ER_TABLEACCESS_DENIED_ERROR
+select next value for s1;
+--error ER_TABLEACCESS_DENIED_ERROR
+do setval(s1,1000,0);
+connection master;
+grant insert on test.* to normal_5@'%' identified by 'pass';
+disconnect m_normal_3;
+connect(m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT);
+insert into t1 values (2);
+select t1.*, (next value for s1) from t1;
+do setval(s1,10000,0);
+select * from s1;
+connection m_normal_2;
+drop table t1;
+drop sequence s1;
+
+--echo #
+--echo # Cleanup
+--echo #
+
+connection master;
+use s_db;
+drop database s_db;
+drop user normal_1@'%';
+drop user normal_2@'%';
+drop user normal_3@'%';
+drop user normal_4@'%';
+drop user normal_5@'%';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/mysqldump.result b/mysql-test/suite/sql_sequence/mysqldump.result
new file mode 100644
index 00000000000..0067709db54
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/mysqldump.result
@@ -0,0 +1,41 @@
+CREATE SEQUENCE a1 engine=aria;
+CREATE TABLE t1(a INT, KEY (a)) KEY_BLOCK_SIZE=1024;
+insert into t1 values (1),(2);
+CREATE SEQUENCE x1 engine=innodb;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `a1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=Aria SEQUENCE=1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO `a1` VALUES (1,1,9223372036854775806,1,1,1000,0,0);
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ KEY `a` (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1024;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO `t1` VALUES (1),(2);
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `x1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=InnoDB SEQUENCE=1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+INSERT INTO `x1` VALUES (1,1,9223372036854775806,1,1,1000,0,0);
+DROP TABLE a1,t1,x1;
diff --git a/mysql-test/suite/sql_sequence/mysqldump.test b/mysql-test/suite/sql_sequence/mysqldump.test
new file mode 100644
index 00000000000..8d5c2d0869d
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/mysqldump.test
@@ -0,0 +1,15 @@
+#
+# Testing mysqldump of sequences
+#
+
+# Embedded server doesn't support external clients
+--source include/not_embedded.inc
+--source include/have_aria.inc
+--source include/have_innodb.inc
+
+CREATE SEQUENCE a1 engine=aria;
+CREATE TABLE t1(a INT, KEY (a)) KEY_BLOCK_SIZE=1024;
+insert into t1 values (1),(2);
+CREATE SEQUENCE x1 engine=innodb;
+--exec $MYSQL_DUMP --compact test
+DROP TABLE a1,t1,x1;
diff --git a/mysql-test/suite/sql_sequence/next.result b/mysql-test/suite/sql_sequence/next.result
new file mode 100644
index 00000000000..a10c131e0e1
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/next.result
@@ -0,0 +1,514 @@
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 2 cycle;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1
+select next value for t1;
+next value for t1
+1
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+3 0
+select next value for t1;
+next value for t1
+2
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+3 0
+select next value for t1;
+next value for t1
+3
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+5 0
+select next value for t1;
+next value for t1
+4
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+5 0
+select next value for t1;
+next value for t1
+5
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+7 0
+select next value for t1;
+next value for t1
+6
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+7 0
+select next value for t1;
+next value for t1
+7
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+9 0
+select next value for t1;
+next value for t1
+8
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+9 0
+select next value for t1;
+next value for t1
+9
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+11 0
+select next value for t1;
+next value for t1
+10
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+11 0
+select next value for t1;
+next value for t1
+1
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+3 1
+select NEXT VALUE for t1,seq from seq_1_to_20;
+NEXT VALUE for t1 seq
+2 1
+3 2
+4 3
+5 4
+6 5
+7 6
+8 7
+9 8
+10 9
+1 10
+2 11
+3 12
+4 13
+5 14
+6 15
+7 16
+8 17
+9 18
+10 19
+1 20
+drop sequence t1;
+CREATE SEQUENCE t1 minvalue 1 maxvalue 10 increment by -1 cache 2 cycle engine=aria;
+select next value for t1;
+next value for t1
+10
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+8 0
+select next value for t1;
+next value for t1
+9
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+8 0
+select next value for t1;
+next value for t1
+8
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+6 0
+select next value for t1;
+next value for t1
+7
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+6 0
+select next value for t1;
+next value for t1
+6
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+4 0
+select next value for t1;
+next value for t1
+5
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+4 0
+select next value for t1;
+next value for t1
+4
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+2 0
+select next value for t1;
+next value for t1
+3
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+2 0
+select next value for t1;
+next value for t1
+2
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+0 0
+select next value for t1;
+next value for t1
+1
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+0 0
+select next value for t1;
+next value for t1
+10
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+8 1
+select NEXT VALUE for t1,seq from seq_1_to_20;
+NEXT VALUE for t1 seq
+9 1
+8 2
+7 3
+6 4
+5 5
+4 6
+3 7
+2 8
+1 9
+10 10
+9 11
+8 12
+7 13
+6 14
+5 15
+4 16
+3 17
+2 18
+1 19
+10 20
+drop sequence t1;
+CREATE SEQUENCE t1 start with 8 minvalue 1 maxvalue 10 increment by 1 cache 2 nocycle;
+select next value for t1;
+next value for t1
+8
+select next value for t1;
+next value for t1
+9
+select next value for t1;
+next value for t1
+10
+select previous value for t1;
+previous value for t1
+10
+select next value for t1;
+ERROR HY000: Sequence 'test.t1' has run out
+select previous value for t1;
+previous value for t1
+NULL
+select next value for t1;
+ERROR HY000: Sequence 'test.t1' has run out
+drop sequence t1;
+create sequence s1 start with 1 cache 2 maxvalue 5;
+select next value for s1;
+next value for s1
+1
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+next value for s1
+3
+select next value for s1;
+next value for s1
+4
+select next value for s1;
+next value for s1
+5
+select next value for s1;
+ERROR HY000: Sequence 'test.s1' has run out
+drop sequence s1;
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 100 increment by 1 cache 10;
+select next value for t1;
+next value for t1
+1
+select * from t1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 100 1 1 10 0 0
+flush tables;
+select next value for t1;
+next value for t1
+11
+select nextval(t1);
+nextval(t1)
+12
+drop sequence t1;
+CREATE SEQUENCE t9 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+select previous value for t9;
+previous value for t9
+NULL
+select next value for t9;
+next value for t9
+1
+select previous value for t9, lastval(t9);
+previous value for t9 lastval(t9)
+1 1
+select next value for t9;
+next value for t9
+2
+select previous value for t9, lastval(t9);
+previous value for t9 lastval(t9)
+2 2
+select seq, previous value for t9, NEXT VALUE for t9, previous value for t9 from seq_1_to_20;
+seq previous value for t9 NEXT VALUE for t9 previous value for t9
+1 2 3 3
+2 3 4 4
+3 4 5 5
+4 5 6 6
+5 6 7 7
+6 7 8 8
+7 8 9 9
+8 9 10 10
+9 10 1 1
+10 1 2 2
+11 2 3 3
+12 3 4 4
+13 4 5 5
+14 5 6 6
+15 6 7 7
+16 7 8 8
+17 8 9 9
+18 9 10 10
+19 10 1 1
+20 1 2 2
+select * from t9;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+6 1 10 1 1 5 1 2
+drop sequence t9;
+CREATE SEQUENCE s1 cache=0;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 0 0 0
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value from s1;
+next_not_cached_value
+2
+select next value for s1;
+next value for s1
+2
+select next_not_cached_value from s1;
+next_not_cached_value
+3
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1 cache=1;
+select next_not_cached_value from s1;
+next_not_cached_value
+1
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value from s1;
+next_not_cached_value
+2
+select next value for s1;
+next value for s1
+2
+select next_not_cached_value from s1;
+next_not_cached_value
+3
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1 cache=2;
+select next_not_cached_value from s1;
+next_not_cached_value
+1
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value from s1;
+next_not_cached_value
+3
+select next value for s1;
+next value for s1
+2
+select next_not_cached_value from s1;
+next_not_cached_value
+3
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1;
+select next value for s1;
+next value for s1
+1
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+next value for s1
+3
+select next value for s1;
+next value for s1
+4
+alter sequence s1 increment -2;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1001 1 9223372036854775806 1 -2 1000 0 0
+select next value for s1;
+next value for s1
+1001
+select next value for s1;
+next value for s1
+999
+alter sequence s1 restart 6;
+select next value for s1;
+next value for s1
+6
+select next value for s1;
+next value for s1
+4
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+ERROR HY000: Sequence 'test.s1' has run out
+DROP SEQUENCE s1;
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+select next value for t1;
+next value for t1
+1
+select previous value for t1;
+previous value for t1
+1
+flush tables;
+select previous value for t1;
+previous value for t1
+1
+drop sequence t1;
+select previous value for t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+CREATE SEQUENCE t1 start with 5 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+select previous value for t1;
+previous value for t1
+NULL
+select next value for t1;
+next value for t1
+5
+select previous value for t1;
+previous value for t1
+5
+drop sequence t1;
+CREATE or replace SEQUENCE s1 MINVALUE 1 MAXVALUE 9999999999
+INCREMENT BY 1 START WITH 3984356 CACHE 20 CYCLE engine=innodb;
+show create table s1;
+Table Create Table
+s1 CREATE TABLE `s1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=InnoDB SEQUENCE=1
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3984356 1 9999999999 3984356 1 20 1 0
+select NEXT VALUE FOR s1;
+NEXT VALUE FOR s1
+3984356
+select NEXT VALUE FOR s1;
+NEXT VALUE FOR s1
+3984357
+select NEXT VALUE FOR s1;
+NEXT VALUE FOR s1
+3984358
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3984376 1 9999999999 3984356 1 20 1 0
+FLUSH TABLES;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3984376 1 9999999999 3984356 1 20 1 0
+select NEXT VALUE FOR s1;
+NEXT VALUE FOR s1
+3984376
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3984396 1 9999999999 3984356 1 20 1 0
+drop sequence s1;
+CREATE SEQUENCE t1 start with 5 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+explain select next value for t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
+explain select next value for t1, minimum_value from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1
+drop table t1;
+CREATE SEQUENCE s1;
+CREATE TABLE t1 (a int);
+insert into t1 values (next value for s1);
+insert into t1 values (next value for s1);
+select * from t1;
+a
+1
+2
+drop table t1,s1;
+CREATE SEQUENCE s1;
+CREATE TABLE t1 (a int primary key auto_increment, b int default 0) engine=myisam;
+insert into t1 values (),(),(),(),(),(),();
+update t1 set b= next value for s1 where a <= 3;
+select * from t1;
+a b
+1 1
+2 2
+3 3
+4 0
+5 0
+6 0
+7 0
+drop table t1,s1;
+CREATE OR REPLACE SEQUENCE s1 MINVALUE 1 MAXVALUE 9999999999 INCREMENT BY 1 START WITH 3984356 nocache CYCLE engine='innodb';
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3984356 1 9999999999 3984356 1 0 1 0
+select next value for s1;
+next value for s1
+3984356
+explain extended select next value for s1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select nextval(`test`.`s1`) AS `next value for s1`
+explain extended select previous value for s1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select lastval(`test`.`s1`) AS `previous value for s1`
+drop sequence s1;
+create table t1 (a int);
+select next value for t1;
+ERROR 42S02: 'test.t1' is not a SEQUENCE
+drop table t1;
+create sequence t1;
+select next value for t1;
+next value for t1
+1
+select next value for t1, minimum_value;
+ERROR 42S22: Unknown column 'minimum_value' in 'field list'
+drop sequence t1;
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+CREATE SEQUENCE s1;
+SELECT
+NEXT VALUE FOR s1,
+PREVIOUS VALUE FOR s1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def NEXT VALUE FOR s1 8 20 1 Y 32896 0 63
+def PREVIOUS VALUE FOR s1 8 20 1 Y 32896 0 63
+NEXT VALUE FOR s1 PREVIOUS VALUE FOR s1
+1 1
+DROP SEQUENCE s1;
diff --git a/mysql-test/suite/sql_sequence/next.test b/mysql-test/suite/sql_sequence/next.test
new file mode 100644
index 00000000000..271c4a6558a
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/next.test
@@ -0,0 +1,262 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+
+#
+# Test sequence generation
+#
+
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 2 cycle;
+show create table t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+
+select NEXT VALUE for t1,seq from seq_1_to_20;
+
+drop sequence t1;
+
+CREATE SEQUENCE t1 minvalue 1 maxvalue 10 increment by -1 cache 2 cycle engine=aria;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+
+select NEXT VALUE for t1,seq from seq_1_to_20;
+
+drop sequence t1;
+
+CREATE SEQUENCE t1 start with 8 minvalue 1 maxvalue 10 increment by 1 cache 2 nocycle;
+select next value for t1;
+select next value for t1;
+select next value for t1;
+select previous value for t1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for t1;
+select previous value for t1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for t1;
+drop sequence t1;
+
+create sequence s1 start with 1 cache 2 maxvalue 5;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for s1;
+drop sequence s1;
+
+#
+# Test that flush tables jumps to next next_not_cached_value
+#
+
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 100 increment by 1 cache 10;
+select next value for t1;
+select * from t1;
+flush tables;
+select next value for t1;
+select nextval(t1);
+drop sequence t1;
+
+#
+# Test currval/previous
+#
+
+CREATE SEQUENCE t9 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+select previous value for t9;
+select next value for t9;
+select previous value for t9, lastval(t9);
+select next value for t9;
+select previous value for t9, lastval(t9);
+select seq, previous value for t9, NEXT VALUE for t9, previous value for t9 from seq_1_to_20;
+select * from t9;
+drop sequence t9;
+
+#
+# CACHE = 0 should be same as CACHE = 1
+#
+CREATE SEQUENCE s1 cache=0;
+select * from s1;
+select next value for s1;
+select next_not_cached_value from s1;
+select next value for s1;
+select next_not_cached_value from s1;
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1 cache=1;
+select next_not_cached_value from s1;
+select next value for s1;
+select next_not_cached_value from s1;
+select next value for s1;
+select next_not_cached_value from s1;
+DROP SEQUENCE s1;
+CREATE SEQUENCE s1 cache=2;
+select next_not_cached_value from s1;
+select next value for s1;
+select next_not_cached_value from s1;
+select next value for s1;
+select next_not_cached_value from s1;
+DROP SEQUENCE s1;
+
+#
+# Negative increment for sequence
+#
+
+CREATE SEQUENCE s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+alter sequence s1 increment -2;
+select * from s1;
+select next value for s1;
+select next value for s1;
+alter sequence s1 restart 6;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for s1;
+DROP SEQUENCE s1;
+
+#
+# Check what happens when one refers to a sequence that has been closed/deleted
+#
+
+CREATE SEQUENCE t1 start with 1 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+select next value for t1;
+select previous value for t1;
+flush tables;
+select previous value for t1;
+drop sequence t1;
+--error ER_NO_SUCH_TABLE
+select previous value for t1;
+CREATE SEQUENCE t1 start with 5 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+select previous value for t1;
+select next value for t1;
+select previous value for t1;
+drop sequence t1;
+
+# This failed in an early build
+
+CREATE or replace SEQUENCE s1 MINVALUE 1 MAXVALUE 9999999999
+INCREMENT BY 1 START WITH 3984356 CACHE 20 CYCLE engine=innodb;
+show create table s1;
+select * from s1;
+select NEXT VALUE FOR s1;
+select NEXT VALUE FOR s1;
+select NEXT VALUE FOR s1;
+select * from s1;
+FLUSH TABLES;
+select * from s1;
+select NEXT VALUE FOR s1;
+select * from s1;
+drop sequence s1;
+
+#
+# Explain
+#
+
+CREATE SEQUENCE t1 start with 5 minvalue 1 maxvalue 10 increment by 1 cache 5 cycle;
+explain select next value for t1;
+explain select next value for t1, minimum_value from t1;
+drop table t1;
+
+#
+# Using insert with NEXT VALUE
+#
+
+CREATE SEQUENCE s1;
+CREATE TABLE t1 (a int);
+insert into t1 values (next value for s1);
+insert into t1 values (next value for s1);
+select * from t1;
+drop table t1,s1;
+
+#
+# Using update with NEXT VALUE
+#
+
+CREATE SEQUENCE s1;
+CREATE TABLE t1 (a int primary key auto_increment, b int default 0) engine=myisam;
+insert into t1 values (),(),(),(),(),(),();
+update t1 set b= next value for s1 where a <= 3;
+select * from t1;
+drop table t1,s1;
+
+#
+# NO CACHE and InnoDB
+#
+
+CREATE OR REPLACE SEQUENCE s1 MINVALUE 1 MAXVALUE 9999999999 INCREMENT BY 1 START WITH 3984356 nocache CYCLE engine='innodb';
+select * from s1;
+select next value for s1;
+explain extended select next value for s1;
+explain extended select previous value for s1;
+drop sequence s1;
+
+#
+# Some error testing
+#
+
+create table t1 (a int);
+--error ER_NOT_SEQUENCE
+select next value for t1;
+drop table t1;
+
+create sequence t1;
+select next value for t1;
+--error ER_BAD_FIELD_ERROR
+select next value for t1, minimum_value;
+drop sequence t1;
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+CREATE SEQUENCE s1;
+SELECT
+ NEXT VALUE FOR s1,
+ PREVIOUS VALUE FOR s1;
+DROP SEQUENCE s1;
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result
new file mode 100644
index 00000000000..90e3a0737c6
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/other.result
@@ -0,0 +1,164 @@
+#
+# Create and check
+#
+create sequence s1 engine=innodb;
+check table s1;
+Table Op Msg_type Msg_text
+test.s1 check note The storage engine for the table doesn't support check
+select next value for s1;
+next value for s1
+1
+flush tables;
+check table s1;
+Table Op Msg_type Msg_text
+test.s1 check note The storage engine for the table doesn't support check
+select next value for s1;
+next value for s1
+1001
+flush tables;
+repair table s1;
+Table Op Msg_type Msg_text
+test.s1 repair note The storage engine for the table doesn't support repair
+select next value for s1;
+next value for s1
+2001
+drop sequence s1;
+create or replace sequence s1 engine=innodb;
+select next value for s1;
+next value for s1
+1
+repair table s1;
+Table Op Msg_type Msg_text
+test.s1 repair note The storage engine for the table doesn't support repair
+check table s1;
+Table Op Msg_type Msg_text
+test.s1 check note The storage engine for the table doesn't support check
+select next value for s1;
+next value for s1
+1001
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+2001 1 9223372036854775806 1 1 1000 0 0
+drop sequence s1;
+#
+# INSERT
+#
+create sequence s1;
+create sequence s2;
+insert into s1 (next_not_cached_value, minimum_value) values (100,1000);
+ERROR HY000: Field 'maximum_value' doesn't have a default value
+insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0);
+ERROR HY000: Table 's1' is specified twice, both as a target for 'INSERT' and as a separate source for data
+insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
+ERROR HY000: Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a squence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead.
+insert into s1 select * from s2;
+ERROR HY000: Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a squence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead.
+insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0);
+ERROR HY000: Sequence 'test.s1' values are conflicting
+insert into s1 values(0,9223372036854775806,1,1,1,1000,0,0);
+ERROR HY000: Sequence 'test.s1' values are conflicting
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+insert into s1 values(1000,1,9223372036854775806,1,1,1000,0,0);
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1000 1 9223372036854775806 1 1 1000 0 0
+select next value for s1;
+next value for s1
+1000
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+2000 1 9223372036854775806 1 1 1000 0 0
+insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0);
+ERROR HY000: Sequence 'test.s2' values are conflicting
+drop sequence s1,s2;
+#
+# UPDATE and DELETE
+#
+create sequence s1;
+update s1 set next_not_cached_value=100;
+ERROR HY000: Storage engine SEQUENCE of the table `test`.`s1` doesn't have this option
+delete from s1 where next_not_cached_value > 0;
+ERROR HY000: Storage engine SEQUENCE of the table `test`.`s1` doesn't have this option
+drop sequence s1;
+#
+# SHOW TABLES
+#
+create sequence s1;
+create table t1 (a int);
+create view v1 as select * from s1;
+show full tables;
+Tables_in_test Table_type
+s1 SEQUENCE
+t1 BASE TABLE
+v1 VIEW
+SELECT TABLE_TYPE,ENGINE FROM INFORMATION_SCHEMA.TABLES where table_schema="test";
+TABLE_TYPE ENGINE
+SEQUENCE MyISAM
+BASE TABLE MyISAM
+VIEW NULL
+drop table t1,s1;
+drop view v1;
+#
+# LOCK TABLES (as in mysqldump)
+#
+create sequence s1 engine=innodb;
+LOCK TABLES s1 READ;
+SELECT * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+UNLOCK TABLES;
+LOCK TABLES s1 WRITE;
+insert into s1 values (1,1,9223372036854775806, 1, 1, 1000, 0, 0);
+UNLOCK TABLES;
+drop table s1;
+#
+# Many sequence calls with innodb
+#
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+count(nextval(s1))
+2000
+commit;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+2001 1 9223372036854775806 1 1 1000 0 0
+drop sequence s1;
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+count(nextval(s1))
+2000
+connect addconroot, localhost, root,,;
+connection addconroot;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+count(nextval(s1))
+2000
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+4001 1 9223372036854775806 1 1 1000 0 0
+commit;
+disconnect addconroot;
+connection default;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+4001 1 9223372036854775806 1 1 1000 0 0
+commit;
+drop sequence s1;
+#
+# Flush tables with read lock
+#
+create sequence s1;
+select next value for s1;
+next value for s1
+1
+flush tables with read lock;
+create sequence s2;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+select next value for s1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop sequence s1;
diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test
new file mode 100644
index 00000000000..d816ec7c108
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/other.test
@@ -0,0 +1,133 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+
+#
+# Test various combinations of operations on sequence
+#
+
+--echo #
+--echo # Create and check
+--echo #
+
+create sequence s1 engine=innodb;
+check table s1;
+select next value for s1;
+flush tables;
+check table s1;
+select next value for s1;
+flush tables;
+repair table s1;
+select next value for s1;
+drop sequence s1;
+
+create or replace sequence s1 engine=innodb;
+select next value for s1;
+repair table s1;
+check table s1;
+select next value for s1;
+select * from s1;
+drop sequence s1;
+
+--echo #
+--echo # INSERT
+--echo #
+
+create sequence s1;
+create sequence s2;
+--error ER_NO_DEFAULT_FOR_FIELD
+insert into s1 (next_not_cached_value, minimum_value) values (100,1000);
+--error ER_UPDATE_TABLE_USED
+insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0);
+--error ER_WRONG_INSERT_INTO_SEQUENCE
+insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
+--error ER_WRONG_INSERT_INTO_SEQUENCE
+insert into s1 select * from s2;
+--error ER_SEQUENCE_INVALID_DATA
+insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0);
+--error ER_SEQUENCE_INVALID_DATA
+insert into s1 values(0,9223372036854775806,1,1,1,1000,0,0);
+select * from s1;
+insert into s1 values(1000,1,9223372036854775806,1,1,1000,0,0);
+select * from s1;
+select next value for s1;
+select * from s1;
+--error ER_SEQUENCE_INVALID_DATA
+insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0);
+drop sequence s1,s2;
+
+--echo #
+--echo # UPDATE and DELETE
+--echo #
+
+create sequence s1;
+--error ER_ILLEGAL_HA
+update s1 set next_not_cached_value=100;
+--error ER_ILLEGAL_HA
+delete from s1 where next_not_cached_value > 0;
+drop sequence s1;
+
+--echo #
+--echo # SHOW TABLES
+--echo #
+
+create sequence s1;
+create table t1 (a int);
+create view v1 as select * from s1;
+show full tables;
+SELECT TABLE_TYPE,ENGINE FROM INFORMATION_SCHEMA.TABLES where table_schema="test";
+drop table t1,s1;
+drop view v1;
+
+--echo #
+--echo # LOCK TABLES (as in mysqldump)
+--echo #
+
+create sequence s1 engine=innodb;
+LOCK TABLES s1 READ;
+SELECT * from s1;
+UNLOCK TABLES;
+LOCK TABLES s1 WRITE;
+insert into s1 values (1,1,9223372036854775806, 1, 1, 1000, 0, 0);
+UNLOCK TABLES;
+drop table s1;
+
+--echo #
+--echo # Many sequence calls with innodb
+--echo #
+
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+commit;
+select * from s1;
+drop sequence s1;
+
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+
+connect (addconroot, localhost, root,,);
+connection addconroot;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+select * from s1;
+commit;
+disconnect addconroot;
+connection default;
+select * from s1;
+commit;
+drop sequence s1;
+
+--echo #
+--echo # Flush tables with read lock
+--echo #
+
+create sequence s1;
+select next value for s1;
+flush tables with read lock;
+--error 1223
+create sequence s2;
+--error 1223
+select next value for s1;
+unlock tables;
+drop sequence s1;
diff --git a/mysql-test/suite/sql_sequence/read_only.result b/mysql-test/suite/sql_sequence/read_only.result
new file mode 100644
index 00000000000..38edcc0894b
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/read_only.result
@@ -0,0 +1,38 @@
+create sequence s1 cache 2 engine=innodb;
+connection default;
+show global variables like 'innodb_read_only';
+Variable_name Value
+innodb_read_only ON
+use test;
+set session binlog_format= row;
+###########################################
+read_only create error.
+###########################################
+show global variables like 'innodb_read_only';
+Variable_name Value
+innodb_read_only ON
+use test;
+create sequence s2 cache 5 engine=innodb;
+ERROR HY000: Can't create table `test`.`s2` (errno: 165 "Table is read only")
+###########################################
+read_only query error.
+###########################################
+select next value for s1;
+ERROR HY000: Table 's1' is read only
+select next value for s1;
+ERROR HY000: Table 's1' is read only
+select next value for s1;
+ERROR HY000: Table 's1' is read only
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 2 0 0
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 2 0 0
+select next value for s1;
+next value for s1
+1
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 1 9223372036854775806 1 1 2 0 0
+drop sequence s1;
diff --git a/mysql-test/suite/sql_sequence/read_only.test b/mysql-test/suite/sql_sequence/read_only.test
new file mode 100644
index 00000000000..73103384882
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/read_only.test
@@ -0,0 +1,44 @@
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+
+#
+# Test innodb read only
+#
+
+create sequence s1 cache 2 engine=innodb;
+
+--let $restart_parameters= --innodb-read-only
+--source include/restart_mysqld.inc
+
+connection default;
+show global variables like 'innodb_read_only';
+use test;
+set session binlog_format= row;
+
+--echo ###########################################
+--echo read_only create error.
+--echo ###########################################
+
+show global variables like 'innodb_read_only';
+use test;
+
+--error ER_CANT_CREATE_TABLE
+create sequence s2 cache 5 engine=innodb;
+
+--echo ###########################################
+--echo read_only query error.
+--echo ###########################################
+--error ER_OPEN_AS_READONLY
+select next value for s1;
+--error ER_OPEN_AS_READONLY
+select next value for s1;
+--error ER_OPEN_AS_READONLY
+select next value for s1;
+
+select * from s1;
+--let $restart_parameters=
+--source include/restart_mysqld.inc
+select * from s1;
+select next value for s1;
+select * from s1;
+drop sequence s1;
diff --git a/mysql-test/suite/sql_sequence/replication-master.opt b/mysql-test/suite/sql_sequence/replication-master.opt
new file mode 100644
index 00000000000..bbea8eabc91
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/replication-master.opt
@@ -0,0 +1 @@
+--binlog_format=row --query_cache_type=1
diff --git a/mysql-test/suite/sql_sequence/replication-slave.opt b/mysql-test/suite/sql_sequence/replication-slave.opt
new file mode 100644
index 00000000000..a4e068e4b43
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/replication-slave.opt
@@ -0,0 +1 @@
+--binlog_format=row --query_cache_type=1 --read_only=true
diff --git a/mysql-test/suite/sql_sequence/replication.result b/mysql-test/suite/sql_sequence/replication.result
new file mode 100644
index 00000000000..5c7d45614e9
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/replication.result
@@ -0,0 +1,1067 @@
+include/master-slave.inc
+[connection master]
+connection master;
+create database s_db;
+use s_db;
+grant all on s_db.* to normal_1@'%' identified by 'pass';
+grant all on test.* to normal_2@'%' identified by 'pass';
+grant all on s_db.* to normal_3@'%' identified by 'pass';
+grant all on test.* to normal_4@'%' identified by 'pass';
+connection slave;
+connect m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT;
+connect m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT;
+connect s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT;
+connect s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT;
+connection slave;
+set global read_only=on;
+use s_db;
+###########################################
+master and slave sync sequence.
+###########################################
+connection master;
+create sequence s1;
+show create table s1;
+Table Create Table
+s1 CREATE TABLE `s1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1
+connection slave;
+show create table s1;
+Table Create Table
+s1 CREATE TABLE `s1` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
+ `increment` bigint(21) NOT NULL COMMENT 'increment value',
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
+ `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
+) ENGINE=MyISAM SEQUENCE=1
+connection master;
+drop sequence s1;
+###########################################
+not support create table engine=sequence.
+###########################################
+connection master;
+create table t(id int)engine=sequence;
+ERROR 42000: Unknown storage engine 'sequence'
+create table t(id int)engine=innodb;
+alter table t engine=sequence;
+ERROR 42000: Unknown storage engine 'sequence'
+drop table t;
+###########################################
+not support alter sequence table.
+###########################################
+connection master;
+create sequence s2;
+alter table s2 add id int;
+ERROR HY000: Sequence 's_db.s2' table structure is invalid (Wrong number of columns)
+alter table s2 add index ind_x(start);
+ERROR HY000: Sequence 's_db.s2' table structure is invalid (Sequence tables cannot have any keys)
+drop sequence s2;
+###########################################
+support create sequence
+###########################################
+connection master;
+create table t_1(id int);
+show create sequence t_1;
+ERROR 42S02: 's_db.t_1' is not a SEQUENCE
+drop table t_1;
+CREATE SEQUENCE `s2` (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) ENGINE=InnoDB sequence=1;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NU' at line 1
+CREATE TABLE `s2` (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) ENGINE=InnoDB sequence=1;
+insert into s2 values(1, 1, 10, 1, 2, 1, 1, 0);
+commit;
+select * for s2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 's2' at line 1
+select * from s2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 10 1 2 1 1 0
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+1
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+3
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+5
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+7
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+9
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+1
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+3
+select * from s2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 10 1 2 1 1 1
+commit;
+connection master;
+connection slave;
+select * from s2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 10 1 2 1 1 1
+connection master;
+drop sequence s2;
+CREATE TABLE `s2` (
+`next_not_cached_value` bigint(21) NOT NULL,
+`minimum_value` bigint(21) NOT NULL,
+`maximum_value` bigint(21) NOT NULL,
+`start_value` bigint(21) NOT NULL,
+`increment` bigint(21) NOT NULL,
+`cache_size` bigint(21) unsigned NOT NULL,
+`cycle_option` tinyint(1) unsigned NOT NULL,
+`cycle_count` bigint(21) NOT NULL
+) ENGINE=myisam DEFAULT CHARSET=latin1 sequence=1;
+show create sequence s2;
+Table Create Table
+s2 CREATE SEQUENCE `s2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+drop sequence s2;
+###########################################
+select sequence syntax test
+###########################################
+connection master;
+create sequence s2;
+create table t2 (id int);
+select * from s2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+select * from t2;
+id
+insert into t2 select next value for s2;
+commit;
+select NEXT VALUE for s2;
+NEXT VALUE for s2
+2
+select NEXT VALUE for t2;
+ERROR 42S02: 's_db.t2' is not a SEQUENCE
+select * from s2, t2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count id
+1001 1 9223372036854775806 1 1 1000 0 0 1
+select * for s2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 's2' at line 1
+select * for s2, t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 's2, t2' at line 1
+connection master;
+drop sequence s2;
+drop table t2;
+###########################################
+support rename, not support truncate
+###########################################
+connection master;
+create sequence s2;
+alter table s2 rename to s2_1;
+rename table s2_1 to s2_2;
+show create sequence s2_2;
+Table Create Table
+s2_2 CREATE SEQUENCE `s2_2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=MyISAM
+select * from s2_2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+truncate table s2_2;
+ERROR HY000: Storage engine SEQUENCE of the table `s_db`.`s2_2` doesn't have this option
+rename table s2_2 to s2;
+drop sequence s2;
+###########################################
+all invalid sequence value
+###########################################
+connection master;
+create sequence s2 start with 1
+minvalue 1
+maxvalue 100000
+increment by 1
+cache 10000
+cycle;
+drop sequence s2;
+create sequence s2 start with 1
+minvalue 1
+maxvalue 100000
+increment by 1
+cache 10000
+nocycle;
+drop sequence s2;
+create sequence s2 start with 1
+minvalue 1
+maxvalue 100000
+increment by 1
+nocache
+nocycle;
+drop sequence s2;
+create sequence s2 start with 1
+minvalue 5
+maxvalue 100000
+increment by 1
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+create sequence s2 start with 1
+minvalue 5
+maxvalue 5
+increment by 1
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+create sequence s2 start with 1
+minvalue 5
+maxvalue 4
+increment by 1
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+create sequence s2 start with 1
+minvalue 5
+maxvalue 4
+increment by 0
+nocache
+nocycle;
+ERROR HY000: Sequence 's_db.s2' values are conflicting
+###########################################
+global read lock prevent query sequence
+###########################################
+connection master;
+create sequence s_db.s1;
+flush table with read lock;
+select NEXT VALUE for s1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop sequence s_db.s1;
+###########################################
+query cache test
+###########################################
+connection master;
+flush status;
+show global variables like 'query_cache_type';
+Variable_name Value
+query_cache_type ON
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 0
+show status like 'Qcache_inserts';
+Variable_name Value
+Qcache_inserts 0
+###########################################
+priv test
+###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+select NEXT VALUE for s_db.s1;
+NEXT VALUE for s_db.s1
+1
+create sequence s_db.s2;
+drop sequence s_db.s2;
+connection m_normal_2;
+select NEXT VALUE for s_db.s1;
+ERROR 42000: INSERT command denied to user 'normal_2'@'localhost' for table 's1'
+create sequence s_db.s2;
+ERROR 42000: CREATE command denied to user 'normal_2'@'localhost' for table 's2'
+connection m_normal_1;
+drop sequence s_db.s1;
+###########################################
+run out sequence value
+###########################################
+connection m_normal_1;
+create sequence s_t start with 1 cache 2 maxvalue 5;
+create table t(id int);
+insert into t values(1111);
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+ERROR HY000: Sequence 's_db.s_t' has run out
+insert into t select next value for s_t;
+ERROR HY000: Sequence 's_db.s_t' has run out
+commit;
+select * from t;
+id
+1111
+1
+2
+3
+4
+5
+connection master;
+connection slave;
+connection s_normal_3;
+select * from t;
+id
+1111
+1
+2
+3
+4
+5
+connection m_normal_1;
+drop sequence s_t;
+drop table t;
+###########################################
+read_only prevent query sequence
+###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+show global variables like 'read_only';
+Variable_name Value
+read_only OFF
+select * from s_db.s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+connection master;
+connection slave;
+connection s_normal_3;
+show global variables like 'read_only';
+Variable_name Value
+read_only ON
+select next value for s_db.s1;
+ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
+connection m_normal_1;
+drop sequence s_db.s1;
+###########################################
+update based table
+###########################################
+connection m_normal_1;
+create sequence s_t start with 1 minvalue 1 maxvalue 20 increment by 1 cache 5 cycle engine=innodb;
+connection master;
+connection slave;
+connection s_normal_3;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 20 1 1 5 1 0
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+1
+connection master;
+connection slave;
+connection s_normal_3;
+select next_not_cached_value from s_t;
+next_not_cached_value
+6
+------------------------------------------
+master ALTER SEQUENCE
+------------------------------------------
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+2
+alter sequence s_t restart= 11;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 20 1 1 5 1 0
+connection master;
+connection slave;
+------------------------------------------
+show slave nextval;
+------------------------------------------
+connection s_normal_3;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 20 1 1 5 1 0
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+11
+connection master;
+connection slave;
+connection s_normal_3;
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+------------------------------------------
+update into invalid sequence
+------------------------------------------
+connection m_normal_1;
+select next value for s_t;
+next value for s_t
+12
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+alter sequence s_t minvalue=11 maxvalue=9;
+ERROR HY000: Sequence 's_db.s_t' values are conflicting
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+alter sequence s_t restart= 12 start=10 minvalue=11 maxvalue=20;
+ERROR HY000: Sequence 's_db.s_t' values are conflicting
+select * from s_t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+16 1 20 1 1 5 1 0
+------------------------------------------
+delete sequence row
+------------------------------------------
+connection m_normal_1;
+delete from s_t;
+ERROR HY000: Storage engine SEQUENCE of the table `s_db`.`s_t` doesn't have this option
+commit;
+select next value for s_t;
+next value for s_t
+13
+connection m_normal_1;
+drop sequence s_t;
+###########################################
+test transaction context (innodb)
+###########################################
+------------------------------------------
+transaction table and sequence
+normal transaction commit
+------------------------------------------
+connection m_normal_1;
+create sequence s_1 cache 5 engine=innodb;
+create table t_1(id int)engine=innodb;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+select * from t_1;
+id
+1111
+1
+2
+2222
+select * from s_1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+6 1 9223372036854775806 1 1 5 0 0
+connection master;
+connection slave;
+connection s_normal_3;
+select * from t_1;
+id
+1111
+1
+2
+2222
+------------------------------------------
+normal transaction rollback
+------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+rollback;
+select * from t_1;
+id
+1111
+1
+2
+2222
+select * from s_1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 9223372036854775806 1 1 5 0 0
+select next value for s_1;
+next value for s_1
+11
+connection master;
+connection slave;
+connection s_normal_3;
+select * from t_1;
+id
+1111
+1
+2
+2222
+connection m_normal_1;
+drop sequence s_1;
+drop table t_1;
+###########################################
+test transaction context (myisam)
+###########################################
+------------------------------------------
+transaction table and sequence
+normal transaction commit
+------------------------------------------
+connection m_normal_1;
+create sequence s_1 cache 5;
+create table t_1(id int)engine=myisam;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+select * from t_1;
+id
+1111
+1
+2
+2222
+connection master;
+connection slave;
+connection s_normal_3;
+select * from t_1;
+id
+1111
+1
+2
+2222
+------------------------------------------
+normal transaction rollback
+------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+rollback;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+select next value for s_1;
+next value for s_1
+11
+connection master;
+connection slave;
+connection s_normal_3;
+select * from t_1;
+id
+1111
+1
+2
+2222
+3333
+3
+4
+5
+6
+7
+8
+9
+10
+connection m_normal_1;
+drop sequence s_1;
+drop table t_1;
+###########################################
+close binlog
+###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+select next value for s1;
+next value for s1
+1
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+next value for s1
+3
+select next value for s1;
+next value for s1
+4
+commit;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 9223372036854775806 1 1 2 0 0
+connection master;
+connection slave;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 9223372036854775806 1 1 2 0 0
+------------------------------------------
+close session binlog.
+------------------------------------------
+connection master;
+set session sql_log_bin=off;
+select next value for s1;
+next value for s1
+5
+select next value for s1;
+next value for s1
+6
+select next value for s1;
+next value for s1
+7
+select next value for s1;
+next value for s1
+8
+set session sql_log_bin=on;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+9 1 9223372036854775806 1 1 2 0 0
+connection master;
+connection slave;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+5 1 9223372036854775806 1 1 2 0 0
+connection master;
+select next value for s1;
+next value for s1
+9
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 9223372036854775806 1 1 2 0 0
+connection slave;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+11 1 9223372036854775806 1 1 2 0 0
+connection master;
+drop sequence s1;
+###########################################
+statement binlog
+###########################################
+------------------------------------------
+set binlog_format=statement
+------------------------------------------
+connection master;
+set session binlog_format=statement;
+show session variables like '%binlog_format%';
+Variable_name Value
+binlog_format STATEMENT
+wsrep_forced_binlog_format NONE
+create sequence s1 cache 2;
+select next value for s1;
+ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.
+set session binlog_format=row;
+select next value for s1;
+next value for s1
+1
+connection master;
+connection slave;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 1 9223372036854775806 1 1 2 0 0
+connection m_normal_1;
+drop sequence s1;
+------------------------------------------
+set binlog_format=mixed
+------------------------------------------
+connection master;
+set session binlog_format=mixed;
+show session variables like '%binlog_format%';
+Variable_name Value
+binlog_format MIXED
+wsrep_forced_binlog_format NONE
+create sequence s1 cache 2;
+select next value for s1;
+next value for s1
+1
+set session binlog_format=row;
+select next value for s1;
+next value for s1
+2
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 1 9223372036854775806 1 1 2 0 0
+connection master;
+connection slave;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+3 1 9223372036854775806 1 1 2 0 0
+connection m_normal_1;
+drop sequence s1;
+connection master;
+connection slave;
+###########################################
+test savepoint
+###########################################
+connection master;
+set session binlog_format=row;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+begin;
+insert into t1 values(1111);
+savepoint sp1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+insert into t1 values(2222);
+select * from t1;
+id
+1111
+1
+2
+3
+2222
+rollback to sp1;
+select * from t1;
+id
+1111
+select next value for s1;
+next value for s1
+4
+commit;
+drop sequence s1;
+drop table t1;
+connection master;
+connection slave;
+###########################################
+create as
+###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+create table t as select * from s1;
+select * from t;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 2 0 0
+drop table t;
+create table t as select next value for s1;
+select * from t;
+next value for s1
+1
+drop table t;
+drop sequence s1;
+connection master;
+connection slave;
+###########################################
+test proc
+###########################################
+connection m_normal_1;
+create table t(id int)engine=innodb;
+create procedure p1()
+begin
+create sequence s1 cache 2;
+end//
+create procedure p2()
+begin
+insert into t select next value for s1;
+commit;
+end//
+call p1();
+call p2();
+call p2();
+call p2();
+call p2();
+select * from t;
+id
+1
+2
+3
+4
+connection master;
+connection slave;
+select * from t;
+id
+1
+2
+3
+4
+connection m_normal_1;
+drop table t;
+drop sequence s1;
+drop procedure p1;
+drop procedure p2;
+###########################################
+test trigger
+###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+create table t2(id int)engine=innodb;
+CREATE TRIGGER tri_1
+before INSERT ON t2 FOR EACH ROW
+BEGIN
+INSERT INTO t1 select next value for s1;
+END//
+begin;
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+select * from t2;
+id
+1111
+1111
+1111
+1111
+select * from t1;
+id
+1
+2
+3
+4
+rollback;
+select * from t2;
+id
+select * from t1;
+id
+select next value for s1;
+next value for s1
+5
+drop trigger tri_1;
+drop table t1;
+drop table t2;
+drop sequence s1;
+###########################################
+test function
+###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+CREATE function f1() returns int
+BEGIN
+INSERT INTO t1 select next value for s1;
+return (1);
+END//
+begin;
+select f1();
+f1()
+1
+select f1();
+f1()
+1
+select f1();
+f1()
+1
+select f1();
+f1()
+1
+select * from t1;
+id
+1
+2
+3
+4
+rollback;
+select * from t1;
+id
+select next value for s1;
+next value for s1
+5
+drop function f1;
+drop table t1;
+drop sequence s1;
+###########################################
+test value boundary
+###########################################
+connection m_normal_1;
+------------------------------------------
+cycle_count increment by cycle_count
+------------------------------------------
+create sequence s1 start with 5 minvalue 2 maxvalue 7 cache 1 cycle;
+select next value for s1;
+next value for s1
+5
+select next value for s1;
+next value for s1
+6
+select next value for s1;
+next value for s1
+7
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+next value for s1
+3
+drop sequence s1;
+create sequence s1 start with 5 minvalue 2 maxvalue 7 cache 10 nocycle;
+select next value for s1;
+next value for s1
+5
+select next value for s1;
+next value for s1
+6
+select next value for s1;
+next value for s1
+7
+select next value for s1;
+ERROR HY000: Sequence 's_db.s1' has run out
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+8 2 7 5 1 10 0 0
+drop sequence s1;
+create sequence s1 start with 2 minvalue 1 maxvalue 3 increment by 3 nocache cycle;
+select next value for s1;
+next value for s1
+2
+select next_not_cached_value,cycle_count from s1;
+next_not_cached_value cycle_count
+4 0
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value,cycle_count from s1;
+next_not_cached_value cycle_count
+4 1
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value,cycle_count from s1;
+next_not_cached_value cycle_count
+4 2
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value,cycle_count from s1;
+next_not_cached_value cycle_count
+4 3
+select next value for s1;
+next value for s1
+1
+select next_not_cached_value,cycle_count from s1;
+next_not_cached_value cycle_count
+4 4
+drop sequence s1;
+create sequence s1 start with 2 minvalue 1 maxvalue 3 increment by 3 cache 2 nocycle;
+select next value for s1;
+next value for s1
+2
+select next value for s1;
+ERROR HY000: Sequence 's_db.s1' has run out
+drop sequence s1;
+------------------------------------------
+beyond ulonglong maxvalue
+------------------------------------------
+create sequence s1 start with 9223372036854775805 minvalue 9223372036854775804 maxvalue 9223372036854775806 cache 1 cycle;
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 0
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775806 0
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775804 0
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 1
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775806 1
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775804 1
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 2
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775806 2
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775804 2
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 3
+drop sequence s1;
+create sequence s1 start with 9223372036854775805 minvalue 9223372036854775804 maxvalue 9223372036854775806 cache 10 cycle;
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 0
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775806 0
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775804 0
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 1
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775806 1
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775804 1
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 2
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775806 2
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775804 2
+select next value for s1, cycle_count from s1;
+next value for s1 cycle_count
+9223372036854775805 3
+drop sequence s1;
+connection master;
+drop database s_db;
+drop user normal_1@'%';
+drop user normal_2@'%';
+drop user normal_3@'%';
+drop user normal_4@'%';
+include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/replication.test b/mysql-test/suite/sql_sequence/replication.test
new file mode 100644
index 00000000000..7bd6f00e2ed
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/replication.test
@@ -0,0 +1,861 @@
+#
+# This test is originally sequence.test from ALISQL by Jianwei modified for
+# MariaDB
+#
+# It tests basic sequence functionallity together with replication
+#
+
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--source include/have_innodb.inc
+
+connection master;
+create database s_db;
+use s_db;
+grant all on s_db.* to normal_1@'%' identified by 'pass';
+grant all on test.* to normal_2@'%' identified by 'pass';
+grant all on s_db.* to normal_3@'%' identified by 'pass';
+grant all on test.* to normal_4@'%' identified by 'pass';
+
+--sync_slave_with_master
+
+connect(m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT);
+connect(m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT);
+
+connect(s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT);
+connect(s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT);
+
+connection slave;
+set global read_only=on;
+use s_db;
+
+--echo ###########################################
+--echo master and slave sync sequence.
+--echo ###########################################
+connection master;
+
+create sequence s1;
+show create table s1;
+
+--sync_slave_with_master
+
+show create table s1;
+
+connection master;
+
+drop sequence s1;
+
+--echo ###########################################
+--echo not support create table engine=sequence.
+--echo ###########################################
+connection master;
+
+--error ER_UNKNOWN_STORAGE_ENGINE
+create table t(id int)engine=sequence;
+
+create table t(id int)engine=innodb;
+
+--error ER_UNKNOWN_STORAGE_ENGINE
+alter table t engine=sequence;
+
+drop table t;
+--echo ###########################################
+--echo not support alter sequence table.
+--echo ###########################################
+connection master;
+
+create sequence s2;
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+alter table s2 add id int;
+
+--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+alter table s2 add index ind_x(start);
+drop sequence s2;
+
+--echo ###########################################
+--echo support create sequence
+--echo ###########################################
+connection master;
+
+create table t_1(id int);
+--error ER_NOT_SEQUENCE
+show create sequence t_1;
+
+drop table t_1;
+
+--error ER_PARSE_ERROR
+CREATE SEQUENCE `s2` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) ENGINE=InnoDB sequence=1;
+
+CREATE TABLE `s2` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) ENGINE=InnoDB sequence=1;
+
+insert into s2 values(1, 1, 10, 1, 2, 1, 1, 0);
+commit;
+--error ER_PARSE_ERROR
+select * for s2;
+select * from s2;
+select NEXT VALUE for s2;
+select NEXT VALUE for s2;
+select NEXT VALUE for s2;
+select NEXT VALUE for s2;
+select NEXT VALUE for s2;
+select NEXT VALUE for s2;
+select NEXT VALUE for s2;
+select * from s2;
+commit;
+
+connection master;
+--sync_slave_with_master
+select * from s2;
+
+connection master;
+drop sequence s2;
+
+CREATE TABLE `s2` (
+ `next_not_cached_value` bigint(21) NOT NULL,
+ `minimum_value` bigint(21) NOT NULL,
+ `maximum_value` bigint(21) NOT NULL,
+ `start_value` bigint(21) NOT NULL,
+ `increment` bigint(21) NOT NULL,
+ `cache_size` bigint(21) unsigned NOT NULL,
+ `cycle_option` tinyint(1) unsigned NOT NULL,
+ `cycle_count` bigint(21) NOT NULL
+) ENGINE=myisam DEFAULT CHARSET=latin1 sequence=1;
+
+show create sequence s2;
+drop sequence s2;
+
+--echo ###########################################
+--echo select sequence syntax test
+--echo ###########################################
+connection master;
+create sequence s2;
+create table t2 (id int);
+
+select * from s2;
+select * from t2;
+insert into t2 select next value for s2;
+commit;
+
+select NEXT VALUE for s2;
+--error ER_NOT_SEQUENCE
+select NEXT VALUE for t2;
+
+select * from s2, t2;
+
+--error ER_PARSE_ERROR
+select * for s2;
+--error ER_PARSE_ERROR
+select * for s2, t2;
+
+connection master;
+drop sequence s2;
+drop table t2;
+
+--echo ###########################################
+--echo support rename, not support truncate
+--echo ###########################################
+connection master;
+
+create sequence s2;
+
+alter table s2 rename to s2_1;
+rename table s2_1 to s2_2;
+show create sequence s2_2;
+select * from s2_2;
+
+--error ER_ILLEGAL_HA
+truncate table s2_2;
+rename table s2_2 to s2;
+drop sequence s2;
+
+--echo ###########################################
+--echo all invalid sequence value
+--echo ###########################################
+
+connection master;
+create sequence s2 start with 1
+ minvalue 1
+ maxvalue 100000
+ increment by 1
+ cache 10000
+ cycle;
+drop sequence s2;
+create sequence s2 start with 1
+ minvalue 1
+ maxvalue 100000
+ increment by 1
+ cache 10000
+ nocycle;
+drop sequence s2;
+create sequence s2 start with 1
+ minvalue 1
+ maxvalue 100000
+ increment by 1
+ nocache
+ nocycle;
+drop sequence s2;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 100000
+ increment by 1
+ nocache
+ nocycle;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 5
+ increment by 1
+ nocache
+ nocycle;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 4
+ increment by 1
+ nocache
+ nocycle;
+
+--error ER_SEQUENCE_INVALID_DATA
+create sequence s2 start with 1
+ minvalue 5
+ maxvalue 4
+ increment by 0
+ nocache
+ nocycle;
+
+--echo ###########################################
+--echo global read lock prevent query sequence
+--echo ###########################################
+connection master;
+create sequence s_db.s1;
+flush table with read lock;
+--error ER_CANT_UPDATE_WITH_READLOCK
+select NEXT VALUE for s1;
+unlock tables;
+drop sequence s_db.s1;
+
+--echo ###########################################
+--echo query cache test
+--echo ###########################################
+connection master;
+flush status;
+show global variables like 'query_cache_type';
+
+show status like 'Qcache_hits';
+show status like 'Qcache_inserts';
+
+--echo ###########################################
+--echo priv test
+--echo ###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+select NEXT VALUE for s_db.s1;
+create sequence s_db.s2;
+drop sequence s_db.s2;
+
+
+connection m_normal_2;
+--error ER_TABLEACCESS_DENIED_ERROR
+select NEXT VALUE for s_db.s1;
+--error ER_TABLEACCESS_DENIED_ERROR
+create sequence s_db.s2;
+
+connection m_normal_1;
+drop sequence s_db.s1;
+
+--echo ###########################################
+--echo run out sequence value
+--echo ###########################################
+connection m_normal_1;
+create sequence s_t start with 1 cache 2 maxvalue 5;
+create table t(id int);
+insert into t values(1111);
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+insert into t select next value for s_t;
+--error ER_SEQUENCE_RUN_OUT
+insert into t select next value for s_t;
+--error ER_SEQUENCE_RUN_OUT
+insert into t select next value for s_t;
+commit;
+select * from t;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from t;
+
+connection m_normal_1;
+drop sequence s_t;
+drop table t;
+
+--echo ###########################################
+--echo read_only prevent query sequence
+--echo ###########################################
+connection m_normal_1;
+create sequence s_db.s1;
+show global variables like 'read_only';
+select * from s_db.s1;
+
+connection master;
+--sync_slave_with_master
+connection s_normal_3;
+
+show global variables like 'read_only';
+--error ER_OPTION_PREVENTS_STATEMENT
+select next value for s_db.s1;
+
+connection m_normal_1;
+drop sequence s_db.s1;
+
+--echo ###########################################
+--echo update based table
+--echo ###########################################
+connection m_normal_1;
+create sequence s_t start with 1 minvalue 1 maxvalue 20 increment by 1 cache 5 cycle engine=innodb;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from s_t;
+
+
+connection m_normal_1;
+select next value for s_t;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select next_not_cached_value from s_t;
+
+--echo ------------------------------------------
+--echo master ALTER SEQUENCE
+--echo ------------------------------------------
+connection m_normal_1;
+select next value for s_t;
+alter sequence s_t restart= 11;
+
+select * from s_t;
+
+connection master;
+--sync_slave_with_master
+
+--echo ------------------------------------------
+--echo show slave nextval;
+--echo ------------------------------------------
+connection s_normal_3;
+select * from s_t;
+
+connection m_normal_1;
+select next value for s_t;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from s_t;
+
+
+--echo ------------------------------------------
+--echo update into invalid sequence
+--echo ------------------------------------------
+connection m_normal_1;
+select next value for s_t;
+select * from s_t;
+--error ER_SEQUENCE_INVALID_DATA
+alter sequence s_t minvalue=11 maxvalue=9;
+select * from s_t;
+--error ER_SEQUENCE_INVALID_DATA
+alter sequence s_t restart= 12 start=10 minvalue=11 maxvalue=20;
+select * from s_t;
+
+--echo ------------------------------------------
+--echo delete sequence row
+--echo ------------------------------------------
+connection m_normal_1;
+--error ER_ILLEGAL_HA
+delete from s_t;
+commit;
+
+select next value for s_t;
+
+connection m_normal_1;
+drop sequence s_t;
+
+--echo ###########################################
+--echo test transaction context (innodb)
+--echo ###########################################
+
+--echo ------------------------------------------
+--echo transaction table and sequence
+--echo normal transaction commit
+--echo ------------------------------------------
+connection m_normal_1;
+create sequence s_1 cache 5 engine=innodb;
+
+create table t_1(id int)engine=innodb;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+
+select * from t_1;
+select * from s_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from t_1;
+
+--echo ------------------------------------------
+--echo normal transaction rollback
+--echo ------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+
+select * from t_1;
+rollback;
+
+select * from t_1;
+select * from s_1;
+select next value for s_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from t_1;
+
+connection m_normal_1;
+drop sequence s_1;
+drop table t_1;
+
+--echo ###########################################
+--echo test transaction context (myisam)
+--echo ###########################################
+
+--echo ------------------------------------------
+--echo transaction table and sequence
+--echo normal transaction commit
+--echo ------------------------------------------
+connection m_normal_1;
+create sequence s_1 cache 5;
+
+create table t_1(id int)engine=myisam;
+begin;
+insert into t_1 values(1111);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 values(2222);
+commit;
+
+select * from t_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from t_1;
+
+--echo ------------------------------------------
+--echo normal transaction rollback
+--echo ------------------------------------------
+connection m_normal_1;
+begin;
+insert into t_1 values(3333);
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+insert into t_1 select next value for s_1;
+
+select * from t_1;
+rollback;
+
+select * from t_1;
+select next value for s_1;
+
+connection master;
+--sync_slave_with_master
+
+connection s_normal_3;
+select * from t_1;
+
+connection m_normal_1;
+drop sequence s_1;
+drop table t_1;
+
+--echo ###########################################
+--echo close binlog
+--echo ###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+
+commit;
+select * from s1;
+
+connection master;
+--sync_slave_with_master
+
+select * from s1;
+
+--echo ------------------------------------------
+--echo close session binlog.
+--echo ------------------------------------------
+connection master;
+set session sql_log_bin=off;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+
+set session sql_log_bin=on;
+select * from s1;
+
+connection master;
+--sync_slave_with_master
+
+select * from s1;
+
+connection master;
+select next value for s1;
+select * from s1;
+--sync_slave_with_master
+
+select * from s1;
+connection master;
+
+drop sequence s1;
+
+--echo ###########################################
+--echo statement binlog
+--echo ###########################################
+--echo ------------------------------------------
+--echo set binlog_format=statement
+--echo ------------------------------------------
+connection master;
+set session binlog_format=statement;
+show session variables like '%binlog_format%';
+create sequence s1 cache 2;
+--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+select next value for s1;
+
+set session binlog_format=row;
+select next value for s1;
+
+connection master;
+--sync_slave_with_master
+
+select * from s1;
+
+connection m_normal_1;
+drop sequence s1;
+
+--echo ------------------------------------------
+--echo set binlog_format=mixed
+--echo ------------------------------------------
+connection master;
+set session binlog_format=mixed;
+show session variables like '%binlog_format%';
+create sequence s1 cache 2;
+select next value for s1;
+
+set session binlog_format=row;
+select next value for s1;
+select * from s1;
+
+connection master;
+--sync_slave_with_master
+
+select * from s1;
+
+connection m_normal_1;
+drop sequence s1;
+connection master;
+--sync_slave_with_master
+
+--echo ###########################################
+--echo test savepoint
+--echo ###########################################
+
+connection master;
+set session binlog_format=row;
+
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+
+begin;
+insert into t1 values(1111);
+savepoint sp1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+insert into t1 select next value for s1;
+
+insert into t1 values(2222);
+
+select * from t1;
+rollback to sp1;
+select * from t1;
+select next value for s1;
+
+commit;
+
+drop sequence s1;
+drop table t1;
+
+connection master;
+--sync_slave_with_master
+
+--echo ###########################################
+--echo create as
+--echo ###########################################
+connection m_normal_1;
+
+create sequence s1 cache 2;
+create table t as select * from s1;
+select * from t;
+drop table t;
+create table t as select next value for s1;
+select * from t;
+drop table t;
+
+drop sequence s1;
+
+connection master;
+--sync_slave_with_master
+
+--echo ###########################################
+--echo test proc
+--echo ###########################################
+connection m_normal_1;
+create table t(id int)engine=innodb;
+
+delimiter //;
+
+create procedure p1()
+begin
+ create sequence s1 cache 2;
+end//
+
+create procedure p2()
+begin
+ insert into t select next value for s1;
+ commit;
+end//
+
+delimiter ;//
+
+call p1();
+call p2();
+call p2();
+call p2();
+call p2();
+
+select * from t;
+
+connection master;
+--sync_slave_with_master
+
+select * from t;
+
+connection m_normal_1;
+drop table t;
+drop sequence s1;
+drop procedure p1;
+drop procedure p2;
+
+--echo ###########################################
+--echo test trigger
+--echo ###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+create table t2(id int)engine=innodb;
+
+delimiter //;
+CREATE TRIGGER tri_1
+ before INSERT ON t2 FOR EACH ROW
+BEGIN
+ INSERT INTO t1 select next value for s1;
+END//
+delimiter ;//
+
+begin;
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+insert into t2 values(1111);
+
+select * from t2;
+select * from t1;
+rollback;
+select * from t2;
+select * from t1;
+
+select next value for s1;
+
+
+drop trigger tri_1;
+drop table t1;
+drop table t2;
+drop sequence s1;
+
+--echo ###########################################
+--echo test function
+--echo ###########################################
+connection m_normal_1;
+create sequence s1 cache 2;
+create table t1(id int)engine=innodb;
+
+delimiter //;
+CREATE function f1() returns int
+BEGIN
+ INSERT INTO t1 select next value for s1;
+ return (1);
+END//
+delimiter ;//
+
+begin;
+select f1();
+select f1();
+select f1();
+select f1();
+
+select * from t1;
+rollback;
+select * from t1;
+
+select next value for s1;
+
+drop function f1;
+drop table t1;
+drop sequence s1;
+
+--echo ###########################################
+--echo test value boundary
+--echo ###########################################
+connection m_normal_1;
+
+--echo ------------------------------------------
+--echo cycle_count increment by cycle_count
+--echo ------------------------------------------
+create sequence s1 start with 5 minvalue 2 maxvalue 7 cache 1 cycle;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+drop sequence s1;
+
+create sequence s1 start with 5 minvalue 2 maxvalue 7 cache 10 nocycle;
+select next value for s1;
+select next value for s1;
+select next value for s1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for s1;
+select * from s1;
+drop sequence s1;
+
+create sequence s1 start with 2 minvalue 1 maxvalue 3 increment by 3 nocache cycle;
+select next value for s1;
+select next_not_cached_value,cycle_count from s1;
+select next value for s1;
+select next_not_cached_value,cycle_count from s1;
+select next value for s1;
+select next_not_cached_value,cycle_count from s1;
+select next value for s1;
+select next_not_cached_value,cycle_count from s1;
+select next value for s1;
+select next_not_cached_value,cycle_count from s1;
+drop sequence s1;
+
+create sequence s1 start with 2 minvalue 1 maxvalue 3 increment by 3 cache 2 nocycle;
+select next value for s1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for s1;
+drop sequence s1;
+
+--echo ------------------------------------------
+--echo beyond ulonglong maxvalue
+--echo ------------------------------------------
+create sequence s1 start with 9223372036854775805 minvalue 9223372036854775804 maxvalue 9223372036854775806 cache 1 cycle;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+drop sequence s1;
+
+create sequence s1 start with 9223372036854775805 minvalue 9223372036854775804 maxvalue 9223372036854775806 cache 10 cycle;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+select next value for s1, cycle_count from s1;
+drop sequence s1;
+
+connection master;
+drop database s_db;
+drop user normal_1@'%';
+drop user normal_2@'%';
+drop user normal_3@'%';
+drop user normal_4@'%';
+
+--source include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/setval.result b/mysql-test/suite/sql_sequence/setval.result
new file mode 100644
index 00000000000..b7cda27cf96
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/setval.result
@@ -0,0 +1,256 @@
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+#
+# Test setval function
+#
+CREATE SEQUENCE t1 cache 10 engine=myisam;
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+1 0
+do setval(t1,10);
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+11 0
+select next value for t1;
+next value for t1
+11
+do setval(t1,12,1);
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+21 0
+select next value for t1;
+next value for t1
+13
+do setval(t1,15,0);
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+21 0
+select next value for t1;
+next value for t1
+15
+select setval(t1,16,0);
+setval(t1,16,0)
+16
+select next value for t1;
+next value for t1
+16
+do setval(t1,1000,0);
+select next value for t1;
+next value for t1
+1000
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+1010 0
+do setval(t1,2000,0);
+select next value for t1;
+next value for t1
+2000
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+2010 0
+select setval(t1,1000,0);
+setval(t1,1000,0)
+NULL
+select next value for t1;
+next value for t1
+2001
+select setval(t1,1000,TRUE);
+setval(t1,1000,TRUE)
+NULL
+select next value for t1;
+next value for t1
+2002
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+2010 0
+select setval(t1,2002,0);
+setval(t1,2002,0)
+NULL
+select next value for t1;
+next value for t1
+2003
+select setval(t1,2010,0);
+setval(t1,2010,0)
+2010
+select next value for t1;
+next value for t1
+2010
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+2020 0
+drop sequence t1;
+#
+# Testing with cycle
+#
+CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+1 0
+select setval(t1,100,0);
+setval(t1,100,0)
+100
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+100 0
+select next value for t1;
+next value for t1
+100
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+101 0
+select setval(t1,100,0);
+setval(t1,100,0)
+NULL
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+101 0
+select next value for t1;
+next value for t1
+1
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+11 1
+select next value for t1;
+next value for t1
+2
+select setval(t1,100,0,1);
+setval(t1,100,0,1)
+100
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+100 1
+select next value for t1;
+next value for t1
+100
+select setval(t1,100,1,2);
+setval(t1,100,1,2)
+100
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+101 2
+select next value for t1;
+next value for t1
+1
+select setval(t1,100,0,3);
+setval(t1,100,0,3)
+100
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+100 3
+select next value for t1;
+next value for t1
+100
+drop sequence t1;
+#
+# Testing extreme values
+#
+CREATE SEQUENCE t1 cache=10 maxvalue=100 engine=innodb;
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+1 0
+select setval(t1,200);
+setval(t1,200)
+200
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+101 0
+select next value for t1;
+ERROR HY000: Sequence 'test.t1' has run out
+drop sequence t1;
+CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+1 0
+select setval(t1,200);
+setval(t1,200)
+200
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+101 0
+select next value for t1;
+next value for t1
+1
+drop sequence t1;
+CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
+select setval(t1,-10);
+setval(t1,-10)
+-10
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+-20 0
+select next value for t1;
+next value for t1
+-20
+select setval(t1,-15);
+setval(t1,-15)
+NULL
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+-120 0
+select next value for t1;
+next value for t1
+-30
+select setval(t1,-500,FALSE);
+setval(t1,-500,FALSE)
+-500
+select next value for t1;
+next value for t1
+-500
+select next value for t1;
+next value for t1
+-510
+select setval(t1,-525,0);
+setval(t1,-525,0)
+-525
+select next value for t1;
+next value for t1
+-525
+select next value for t1;
+next value for t1
+-535
+drop sequence t1;
+CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
+select setval(t1,-10,0);
+setval(t1,-10,0)
+-10
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+-10 0
+select next value for t1;
+next value for t1
+-10
+drop sequence t1;
+#
+# Other testing
+#
+CREATE SEQUENCE t1;
+select setval(t1,10,0),setval(t1,15,1),setval(t1,5,1);
+setval(t1,10,0) setval(t1,15,1) setval(t1,5,1)
+10 15 NULL
+select next value for t1;
+next value for t1
+16
+select next_not_cached_value,cycle_count from t1;
+next_not_cached_value cycle_count
+1016 0
+explain extended select setval(t1,100),setval(t1,100,TRUE),setval(t1,100,FALSE,50);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select setval(`test`.`t1`,100,1,0) AS `setval(t1,100)`,setval(`test`.`t1`,100,1,0) AS `setval(t1,100,TRUE)`,setval(`test`.`t1`,100,0,50) AS `setval(t1,100,FALSE,50)`
+drop sequence t1;
+create table t1 (a int);
+select setval(t1,10);
+ERROR 42S02: 'test.t1' is not a SEQUENCE
+drop table t1;
+#
+# MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+#
+CREATE SEQUENCE s1;
+SELECT SETVAL(s1,10);
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def SETVAL(s1,10) 8 20 2 Y 32896 0 63
+SETVAL(s1,10)
+10
+DROP SEQUENCE s1;
diff --git a/mysql-test/suite/sql_sequence/setval.test b/mysql-test/suite/sql_sequence/setval.test
new file mode 100644
index 00000000000..8f8059fdcae
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/setval.test
@@ -0,0 +1,139 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+
+drop table if exists t1;
+
+--echo #
+--echo # Test setval function
+--echo #
+
+CREATE SEQUENCE t1 cache 10 engine=myisam;
+select next_not_cached_value,cycle_count from t1;
+do setval(t1,10);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+do setval(t1,12,1);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+do setval(t1,15,0);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select setval(t1,16,0);
+select next value for t1;
+do setval(t1,1000,0);
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+do setval(t1,2000,0);
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+# Set smaller value
+select setval(t1,1000,0);
+select next value for t1;
+select setval(t1,1000,TRUE);
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select setval(t1,2002,0);
+select next value for t1;
+select setval(t1,2010,0);
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+drop sequence t1;
+
+--echo #
+--echo # Testing with cycle
+--echo #
+
+CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
+select next_not_cached_value,cycle_count from t1;
+select setval(t1,100,0);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select setval(t1,100,0);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select setval(t1,100,0,1);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select setval(t1,100,1,2);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select setval(t1,100,0,3);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+drop sequence t1;
+
+--echo #
+--echo # Testing extreme values
+--echo #
+
+CREATE SEQUENCE t1 cache=10 maxvalue=100 engine=innodb;
+select next_not_cached_value,cycle_count from t1;
+select setval(t1,200);
+select next_not_cached_value,cycle_count from t1;
+--error ER_SEQUENCE_RUN_OUT
+select next value for t1;
+drop sequence t1;
+
+CREATE SEQUENCE t1 cache=10 maxvalue=100 cycle engine=innodb;
+select next_not_cached_value,cycle_count from t1;
+select setval(t1,200);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+drop sequence t1;
+
+CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
+select setval(t1,-10);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select setval(t1,-15);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+select setval(t1,-500,FALSE);
+select next value for t1;
+select next value for t1;
+select setval(t1,-525,0);
+select next value for t1;
+select next value for t1;
+drop sequence t1;
+
+CREATE SEQUENCE t1 cache=10 maxvalue=0 increment=-10;
+select setval(t1,-10,0);
+select next_not_cached_value,cycle_count from t1;
+select next value for t1;
+drop sequence t1;
+
+--echo #
+--echo # Other testing
+--echo #
+
+CREATE SEQUENCE t1;
+select setval(t1,10,0),setval(t1,15,1),setval(t1,5,1);
+select next value for t1;
+select next_not_cached_value,cycle_count from t1;
+explain extended select setval(t1,100),setval(t1,100,TRUE),setval(t1,100,FALSE,50);
+drop sequence t1;
+
+#
+# Some error testing
+#
+
+create table t1 (a int);
+--error ER_NOT_SEQUENCE
+select setval(t1,10);
+drop table t1;
+
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+CREATE SEQUENCE s1;
+SELECT SETVAL(s1,10);
+DROP SEQUENCE s1;
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/suite/sql_sequence/temporary.result b/mysql-test/suite/sql_sequence/temporary.result
new file mode 100644
index 00000000000..4885b5f8a26
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/temporary.result
@@ -0,0 +1,12 @@
+#
+# Create
+#
+create temporary sequence s1 engine=innodb;
+alter table s1 engine myisam;
+select nextval(s1);
+nextval(s1)
+1
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1001 1 9223372036854775806 1 1 1000 0 0
+drop temporary sequence s1;
diff --git a/mysql-test/suite/sql_sequence/temporary.test b/mysql-test/suite/sql_sequence/temporary.test
new file mode 100644
index 00000000000..158f6b4961e
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/temporary.test
@@ -0,0 +1,16 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+
+#
+# Test temporary sequences
+#
+
+--echo #
+--echo # Create
+--echo #
+
+create temporary sequence s1 engine=innodb;
+alter table s1 engine myisam;
+select nextval(s1);
+select * from s1;
+drop temporary sequence s1;
diff --git a/mysql-test/suite/sql_sequence/view.result b/mysql-test/suite/sql_sequence/view.result
new file mode 100644
index 00000000000..bd773dcc042
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/view.result
@@ -0,0 +1,26 @@
+create sequence s1;
+create view v1 as select * from s1;
+create view v2 as select next value for s1;
+select * from v1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+select * from v2;
+next value for s1
+1
+select * from v2;
+next value for s1
+2
+select next value for v1;
+ERROR 42S02: 'test.v1' is not a SEQUENCE
+drop sequence s1;
+drop view v1,v2;
+#
+# MDEV 13020 Server crashes in Item_func_nextval::val_int upon
+# selecting NEXT or PREVIOUS VALUE for a view
+#
+CREATE OR REPLACE VIEW v1 AS SELECT 1 AS f;
+SELECT NEXT VALUE FOR v1;
+ERROR 42S02: 'test.v1' is not a SEQUENCE
+SELECT PREVIOUS VALUE FOR v1;
+ERROR 42S02: 'test.v1' is not a SEQUENCE
+drop view v1;
diff --git a/mysql-test/suite/sql_sequence/view.test b/mysql-test/suite/sql_sequence/view.test
new file mode 100644
index 00000000000..fe968604b5b
--- /dev/null
+++ b/mysql-test/suite/sql_sequence/view.test
@@ -0,0 +1,29 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+
+#
+# Test sequences with views
+#
+
+create sequence s1;
+create view v1 as select * from s1;
+create view v2 as select next value for s1;
+select * from v1;
+select * from v2;
+select * from v2;
+--error ER_NOT_SEQUENCE
+select next value for v1;
+drop sequence s1;
+drop view v1,v2;
+
+--echo #
+--echo # MDEV 13020 Server crashes in Item_func_nextval::val_int upon
+--echo # selecting NEXT or PREVIOUS VALUE for a view
+--echo #
+
+CREATE OR REPLACE VIEW v1 AS SELECT 1 AS f;
+--error ER_NOT_SEQUENCE
+SELECT NEXT VALUE FOR v1;
+--error ER_NOT_SEQUENCE
+SELECT PREVIOUS VALUE FOR v1;
+drop view v1;
diff --git a/mysql-test/suite/storage_engine/create_table.result b/mysql-test/suite/storage_engine/create_table.result
index 6936854eb65..2ca144fe50c 100644
--- a/mysql-test/suite/storage_engine/create_table.result
+++ b/mysql-test/suite/storage_engine/create_table.result
@@ -27,7 +27,7 @@ CREATE TABLE t1 ENGINE=<STORAGE_ENGINE> <CUSTOM_TABLE_OPTIONS> AS SELECT 1 UNION
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `1` bigint(20) NOT NULL DEFAULT 0
+ `1` int(1) NOT NULL DEFAULT 0
) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1
SELECT * FROM t1;
1
diff --git a/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result b/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result
index 98072169fc9..760cca25497 100644
--- a/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result
+++ b/mysql-test/suite/sys_vars/r/automatic_sp_privileges_basic.result
@@ -84,12 +84,8 @@ SELECT @@automatic_sp_privileges = @@global.automatic_sp_privileges;
'#---------------------FN_DYNVARS_004_10----------------------#'
SET automatic_sp_privileges = 1;
ERROR HY000: Variable 'automatic_sp_privileges' is a GLOBAL variable and should be set with SET GLOBAL
-SET local.automatic_sp_privileges = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'automatic_sp_privileges = 1' at line 1
SELECT local.automatic_sp_privileges;
ERROR 42S02: Unknown table 'local' in field list
-SET global.automatic_sp_privileges = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'automatic_sp_privileges = 1' at line 1
SELECT global.automatic_sp_privileges;
ERROR 42S02: Unknown table 'global' in field list
SELECT automatic_sp_privileges = @@session.automatic_sp_privileges;
diff --git a/mysql-test/suite/sys_vars/r/big_tables_basic.result b/mysql-test/suite/sys_vars/r/big_tables_basic.result
index 4ff5774812a..29781987d47 100644
--- a/mysql-test/suite/sys_vars/r/big_tables_basic.result
+++ b/mysql-test/suite/sys_vars/r/big_tables_basic.result
@@ -86,12 +86,8 @@ SET big_tables = 1;
SELECT @@big_tables;
@@big_tables
1
-SET local.big_tables = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'big_tables = 1' at line 1
SELECT local.big_tables;
ERROR 42S02: Unknown table 'local' in field list
-SET session.big_tables = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'big_tables = 1' at line 1
SELECT session.big_tables;
ERROR 42S02: Unknown table 'session' in field list
select big_tables;
diff --git a/mysql-test/suite/sys_vars/r/binlog_cache_size_basic.result b/mysql-test/suite/sys_vars/r/binlog_cache_size_basic.result
index d83caffb5be..680e62162a7 100644
--- a/mysql-test/suite/sys_vars/r/binlog_cache_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/binlog_cache_size_basic.result
@@ -96,8 +96,6 @@ SELECT @@binlog_cache_size = @@global.binlog_cache_size;
'#---------------------FN_DYNVARS_006_09----------------------#'
SET binlog_cache_size = 1;
ERROR HY000: Variable 'binlog_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.binlog_cache_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'binlog_cache_size = 1' at line 1
SELECT global.binlog_cache_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT binlog_cache_size = @@session.binlog_cache_size;
diff --git a/mysql-test/suite/sys_vars/r/binlog_stmt_cache_size_basic.result b/mysql-test/suite/sys_vars/r/binlog_stmt_cache_size_basic.result
index 94519d3cd23..f16a36eefa4 100644
--- a/mysql-test/suite/sys_vars/r/binlog_stmt_cache_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/binlog_stmt_cache_size_basic.result
@@ -96,8 +96,6 @@ SELECT @@binlog_stmt_cache_size = @@global.binlog_stmt_cache_size;
'#---------------------FN_DYNVARS_006_09----------------------#'
SET binlog_stmt_cache_size = 1;
ERROR HY000: Variable 'binlog_stmt_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.binlog_stmt_cache_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'binlog_stmt_cache_size = 1' at line 1
SELECT global.binlog_stmt_cache_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT binlog_stmt_cache_size = @@session.binlog_stmt_cache_size;
diff --git a/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic.result b/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic.result
index 1b8e000ad81..97083da7033 100644
--- a/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic.result
@@ -133,12 +133,8 @@ SET bulk_insert_buffer_size = 1;
SELECT @@bulk_insert_buffer_size;
@@bulk_insert_buffer_size
1
-SET local.bulk_insert_buffer_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'bulk_insert_buffer_size = 1' at line 1
SELECT local.bulk_insert_buffer_size;
ERROR 42S02: Unknown table 'local' in field list
-SET session.bulk_insert_buffer_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'bulk_insert_buffer_size = 1' at line 1
SELECT session.bulk_insert_buffer_size;
ERROR 42S02: Unknown table 'session' in field list
SELECT bulk_insert_buffer_size = @@session.bulk_insert_buffer_size;
diff --git a/mysql-test/suite/sys_vars/r/character_set_client_basic.result b/mysql-test/suite/sys_vars/r/character_set_client_basic.result
index e6502d63c78..749e669dd26 100644
--- a/mysql-test/suite/sys_vars/r/character_set_client_basic.result
+++ b/mysql-test/suite/sys_vars/r/character_set_client_basic.result
@@ -21,8 +21,6 @@ SET character_set_client=utf8;
SELECT @@session.character_set_client;
@@session.character_set_client
utf8
-SET global.character_set_client=utf8;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'character_set_client=utf8' at line 1
SET session character_set_client=utf8;
SELECT session character_set_client;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/character_set_connection_basic.result b/mysql-test/suite/sys_vars/r/character_set_connection_basic.result
index ad9e9c80902..ee550ee105f 100644
--- a/mysql-test/suite/sys_vars/r/character_set_connection_basic.result
+++ b/mysql-test/suite/sys_vars/r/character_set_connection_basic.result
@@ -21,8 +21,6 @@ SET character_set_connection=utf8;
SELECT @@session.character_set_connection;
@@session.character_set_connection
utf8
-SET global.character_set_connection=utf8;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'character_set_connection=utf8' at line 1
SET session character_set_connection=utf8;
SELECT session character_set_connection;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/character_set_database_basic.result b/mysql-test/suite/sys_vars/r/character_set_database_basic.result
index 2fec211cf8d..4ced9231560 100644
--- a/mysql-test/suite/sys_vars/r/character_set_database_basic.result
+++ b/mysql-test/suite/sys_vars/r/character_set_database_basic.result
@@ -21,8 +21,6 @@ SET character_set_database=utf8;
SELECT @@session.character_set_database;
@@session.character_set_database
utf8
-SET global.character_set_database=utf8;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'character_set_database=utf8' at line 1
SET session character_set_database=utf8;
SELECT session character_set_database;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/character_set_filesystem_basic.result b/mysql-test/suite/sys_vars/r/character_set_filesystem_basic.result
index c1a77b73fb3..7a32f92deeb 100644
--- a/mysql-test/suite/sys_vars/r/character_set_filesystem_basic.result
+++ b/mysql-test/suite/sys_vars/r/character_set_filesystem_basic.result
@@ -21,8 +21,6 @@ SET character_set_filesystem=utf8;
SELECT @@session.character_set_filesystem;
@@session.character_set_filesystem
utf8
-SET global.character_set_filesystem=utf8;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'character_set_filesystem=utf8' at line 1
SET session character_set_filesystem=utf8;
SELECT session character_set_filesystem;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/character_set_results_basic.result b/mysql-test/suite/sys_vars/r/character_set_results_basic.result
index 244fa4670b8..7fc498fa735 100644
--- a/mysql-test/suite/sys_vars/r/character_set_results_basic.result
+++ b/mysql-test/suite/sys_vars/r/character_set_results_basic.result
Binary files differ
diff --git a/mysql-test/suite/sys_vars/r/character_set_server_basic.result b/mysql-test/suite/sys_vars/r/character_set_server_basic.result
index 0a009cdebdb..84f6819aae2 100644
--- a/mysql-test/suite/sys_vars/r/character_set_server_basic.result
+++ b/mysql-test/suite/sys_vars/r/character_set_server_basic.result
@@ -21,8 +21,6 @@ SET character_set_server=utf8;
SELECT @@session.character_set_server;
@@session.character_set_server
utf8
-SET global.character_set_server=utf8;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'character_set_server=utf8' at line 1
SET session character_set_server=utf8;
SELECT session character_set_server;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/collation_connection_basic.result b/mysql-test/suite/sys_vars/r/collation_connection_basic.result
index 5f8d64e8fa3..eeab4885790 100644
--- a/mysql-test/suite/sys_vars/r/collation_connection_basic.result
+++ b/mysql-test/suite/sys_vars/r/collation_connection_basic.result
@@ -21,8 +21,6 @@ SET collation_connection=utf8_unicode_ci;
SELECT @@session.collation_connection;
@@session.collation_connection
utf8_unicode_ci
-SET global.collation_connection=utf8_unicode_ci;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'collation_connection=utf8_unicode_ci' at line 1
SET session collation_connection=utf8_unicode_ci;
SELECT session collation_connection;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/collation_database_basic.result b/mysql-test/suite/sys_vars/r/collation_database_basic.result
index 5a218167bdb..b99a5ac29df 100644
--- a/mysql-test/suite/sys_vars/r/collation_database_basic.result
+++ b/mysql-test/suite/sys_vars/r/collation_database_basic.result
@@ -21,8 +21,6 @@ SET collation_database=utf8_unicode_ci;
SELECT @@session.collation_database;
@@session.collation_database
utf8_unicode_ci
-SET global.collation_database=utf8_unicode_ci;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'collation_database=utf8_unicode_ci' at line 1
SET session collation_database=utf8_unicode_ci;
SELECT session collation_database;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/collation_server_basic.result b/mysql-test/suite/sys_vars/r/collation_server_basic.result
index 352aeb9ce15..ffe5218f21c 100644
--- a/mysql-test/suite/sys_vars/r/collation_server_basic.result
+++ b/mysql-test/suite/sys_vars/r/collation_server_basic.result
@@ -21,8 +21,6 @@ SET collation_server=utf8_unicode_ci;
SELECT @@session.collation_server;
@@session.collation_server
utf8_unicode_ci
-SET global.collation_server=utf8_unicode_ci;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'collation_server=utf8_unicode_ci' at line 1
SET session collation_server=utf8_unicode_ci;
SELECT session collation_server;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/completion_type_basic.result b/mysql-test/suite/sys_vars/r/completion_type_basic.result
index 9470a7e6100..7f468121219 100644
--- a/mysql-test/suite/sys_vars/r/completion_type_basic.result
+++ b/mysql-test/suite/sys_vars/r/completion_type_basic.result
@@ -118,12 +118,8 @@ SET completion_type = 1;
SELECT @@completion_type;
@@completion_type
CHAIN
-SET local.completion_type = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'completion_type = 1' at line 1
SELECT local.completion_type;
ERROR 42S02: Unknown table 'local' in field list
-SET session.completion_type = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'completion_type = 1' at line 1
SELECT session.completion_type;
ERROR 42S02: Unknown table 'session' in field list
SELECT completion_type = @@session.completion_type;
diff --git a/mysql-test/suite/sys_vars/r/concurrent_insert_basic.result b/mysql-test/suite/sys_vars/r/concurrent_insert_basic.result
index af3d25ff58e..92e6a167c01 100644
--- a/mysql-test/suite/sys_vars/r/concurrent_insert_basic.result
+++ b/mysql-test/suite/sys_vars/r/concurrent_insert_basic.result
@@ -101,8 +101,6 @@ ERROR HY000: Variable 'concurrent_insert' is a GLOBAL variable and should be set
SELECT @@concurrent_insert;
@@concurrent_insert
AUTO
-SET global.concurrent_insert = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'concurrent_insert = 1' at line 1
SELECT global.concurrent_insert;
ERROR 42S02: Unknown table 'global' in field list
SELECT concurrent_insert = @@session.concurrent_insert;
diff --git a/mysql-test/suite/sys_vars/r/connect_timeout_basic.result b/mysql-test/suite/sys_vars/r/connect_timeout_basic.result
index 985ca925491..d0a6a650e21 100644
--- a/mysql-test/suite/sys_vars/r/connect_timeout_basic.result
+++ b/mysql-test/suite/sys_vars/r/connect_timeout_basic.result
@@ -81,8 +81,6 @@ SELECT @@connect_timeout = @@global.connect_timeout;
'#---------------------FN_DYNVARS_019_09----------------------#'
SET connect_timeout = 1;
ERROR HY000: Variable 'connect_timeout' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.connect_timeout = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'connect_timeout = 1' at line 1
SELECT global.connect_timeout;
ERROR 42S02: Unknown table 'global' in field list
SELECT connect_timeout = @@session.connect_timeout;
diff --git a/mysql-test/suite/sys_vars/r/default_master_connection_basic.result b/mysql-test/suite/sys_vars/r/default_master_connection_basic.result
index 78425049324..bb82e3d5bd6 100644
--- a/mysql-test/suite/sys_vars/r/default_master_connection_basic.result
+++ b/mysql-test/suite/sys_vars/r/default_master_connection_basic.result
@@ -78,12 +78,8 @@ SET default_master_connection = 'foo';
SELECT @@default_master_connection;
@@default_master_connection
foo
-SET local.default_master_connection = 'foo';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'default_master_connection = 'foo'' at line 1
SELECT local.default_master_connection;
ERROR 42S02: Unknown table 'local' in field list
-SET session.default_master_connection = 'foo';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'default_master_connection = 'foo'' at line 1
SELECT session.default_master_connection;
ERROR 42S02: Unknown table 'session' in field list
SELECT default_master_connection = @@session.default_master_connection;
diff --git a/mysql-test/suite/sys_vars/r/default_week_format_basic.result b/mysql-test/suite/sys_vars/r/default_week_format_basic.result
index 1ba931734e9..4e9ee26ef9a 100644
--- a/mysql-test/suite/sys_vars/r/default_week_format_basic.result
+++ b/mysql-test/suite/sys_vars/r/default_week_format_basic.result
@@ -151,12 +151,8 @@ SET default_week_format = 1;
SELECT @@default_week_format;
@@default_week_format
1
-SET local.default_week_format = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'default_week_format = 1' at line 1
SELECT local.default_week_format;
ERROR 42S02: Unknown table 'local' in field list
-SET session.default_week_format = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'default_week_format = 1' at line 1
SELECT session.default_week_format;
ERROR 42S02: Unknown table 'session' in field list
SELECT default_week_format = @@session.default_week_format;
diff --git a/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic.result b/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic.result
index 6acc2398bbd..f57fe02f810 100644
--- a/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic.result
+++ b/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic.result
@@ -95,12 +95,8 @@ ERROR HY000: Variable 'delayed_insert_limit' is a GLOBAL variable and should be
SELECT @@delayed_insert_limit;
@@delayed_insert_limit
1
-SET local.delayed_insert_limit = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delayed_insert_limit = 1' at line 1
SELECT local.delayed_insert_limit;
ERROR 42S02: Unknown table 'local' in field list
-SET global.delayed_insert_limit = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delayed_insert_limit = 1' at line 1
SELECT global.delayed_insert_limit;
ERROR 42S02: Unknown table 'global' in field list
SELECT delayed_insert_limit = @@session.delayed_insert_limit;
diff --git a/mysql-test/suite/sys_vars/r/delayed_insert_timeout_basic.result b/mysql-test/suite/sys_vars/r/delayed_insert_timeout_basic.result
index 7b2f98e3682..f9978929698 100644
--- a/mysql-test/suite/sys_vars/r/delayed_insert_timeout_basic.result
+++ b/mysql-test/suite/sys_vars/r/delayed_insert_timeout_basic.result
@@ -93,12 +93,8 @@ ERROR HY000: Variable 'delayed_insert_timeout' is a GLOBAL variable and should b
SELECT @@delayed_insert_timeout;
@@delayed_insert_timeout
1
-SET local.delayed_insert_timeout = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delayed_insert_timeout = 1' at line 1
SELECT local.delayed_insert_timeout;
ERROR 42S02: Unknown table 'local' in field list
-SET global.delayed_insert_timeout = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delayed_insert_timeout = 1' at line 1
SELECT global.delayed_insert_timeout;
ERROR 42S02: Unknown table 'global' in field list
SELECT delayed_insert_timeout = @@session.delayed_insert_timeout;
diff --git a/mysql-test/suite/sys_vars/r/delayed_queue_size_basic.result b/mysql-test/suite/sys_vars/r/delayed_queue_size_basic.result
index 04aad26f0e8..61bd04965fe 100644
--- a/mysql-test/suite/sys_vars/r/delayed_queue_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/delayed_queue_size_basic.result
@@ -93,12 +93,8 @@ ERROR HY000: Variable 'delayed_queue_size' is a GLOBAL variable and should be se
SELECT @@delayed_queue_size;
@@delayed_queue_size
1
-SET local.delayed_queue_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delayed_queue_size = 1' at line 1
SELECT local.delayed_queue_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.delayed_queue_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delayed_queue_size = 1' at line 1
SELECT global.delayed_queue_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT delayed_queue_size = @@session.delayed_queue_size;
diff --git a/mysql-test/suite/sys_vars/r/div_precision_increment_basic.result b/mysql-test/suite/sys_vars/r/div_precision_increment_basic.result
index 570824f8df6..db2fb18562f 100644
--- a/mysql-test/suite/sys_vars/r/div_precision_increment_basic.result
+++ b/mysql-test/suite/sys_vars/r/div_precision_increment_basic.result
@@ -167,12 +167,8 @@ SET div_precision_increment = 1;
SELECT @@div_precision_increment;
@@div_precision_increment
1
-SET local.div_precision_increment = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'div_precision_increment = 1' at line 1
SELECT local.div_precision_increment;
ERROR 42S02: Unknown table 'local' in field list
-SET session.div_precision_increment = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'div_precision_increment = 1' at line 1
SELECT session.div_precision_increment;
ERROR 42S02: Unknown table 'session' in field list
SELECT div_precision_increment = @@session.div_precision_increment;
diff --git a/mysql-test/suite/sys_vars/r/event_scheduler_basic.result b/mysql-test/suite/sys_vars/r/event_scheduler_basic.result
index 04d3f5e5888..920b9ebbbfa 100644
--- a/mysql-test/suite/sys_vars/r/event_scheduler_basic.result
+++ b/mysql-test/suite/sys_vars/r/event_scheduler_basic.result
@@ -83,12 +83,8 @@ SELECT @@event_scheduler = @@global.event_scheduler;
'#---------------------FN_DYNVARS_004_09----------------------#'
SET event_scheduler = ON;
ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
-SET local.event_scheduler = OFF;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'event_scheduler = OFF' at line 1
SELECT local.event_scheduler;
ERROR 42S02: Unknown table 'local' in field list
-SET global.event_scheduler = ON;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'event_scheduler = ON' at line 1
SELECT global.event_scheduler;
ERROR 42S02: Unknown table 'global' in field list
SELECT event_scheduler = @@session.event_scheduler;
diff --git a/mysql-test/suite/sys_vars/r/expire_logs_days_basic.result b/mysql-test/suite/sys_vars/r/expire_logs_days_basic.result
index d55ad7a73b9..f36fbd17321 100644
--- a/mysql-test/suite/sys_vars/r/expire_logs_days_basic.result
+++ b/mysql-test/suite/sys_vars/r/expire_logs_days_basic.result
@@ -113,12 +113,8 @@ ERROR HY000: Variable 'expire_logs_days' is a GLOBAL variable and should be set
SELECT @@expire_logs_days;
@@expire_logs_days
1
-SET local.expire_logs_days = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'expire_logs_days = 1' at line 1
SELECT local.expire_logs_days;
ERROR 42S02: Unknown table 'local' in field list
-SET global.expire_logs_days = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'expire_logs_days = 1' at line 1
SELECT global.expire_logs_days;
ERROR 42S02: Unknown table 'global' in field list
SELECT expire_logs_days = @@session.expire_logs_days;
diff --git a/mysql-test/suite/sys_vars/r/flush_basic.result b/mysql-test/suite/sys_vars/r/flush_basic.result
index fabbf476052..78a2875f89e 100644
--- a/mysql-test/suite/sys_vars/r/flush_basic.result
+++ b/mysql-test/suite/sys_vars/r/flush_basic.result
@@ -83,8 +83,6 @@ SELECT @@flush = @@global.flush;
'#---------------------FN_DYNVARS_030_09----------------------#'
SET flush = 1;
ERROR HY000: Variable 'flush' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.flush = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'flush = 1' at line 1
SELECT global.flush;
ERROR 42S02: Unknown table 'global' in field list
SELECT flush = @@session.flush;
diff --git a/mysql-test/suite/sys_vars/r/general_log_basic.result b/mysql-test/suite/sys_vars/r/general_log_basic.result
index 1d16bc7c4d5..fe8e08e5e3b 100644
--- a/mysql-test/suite/sys_vars/r/general_log_basic.result
+++ b/mysql-test/suite/sys_vars/r/general_log_basic.result
@@ -78,12 +78,8 @@ SELECT @@general_log = @@global.general_log;
'#---------------------FN_DYNVARS_004_09----------------------#'
SET general_log = ON;
ERROR HY000: Variable 'general_log' is a GLOBAL variable and should be set with SET GLOBAL
-SET local.general_log = OFF;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'general_log = OFF' at line 1
SELECT local.general_log;
ERROR 42S02: Unknown table 'local' in field list
-SET global.general_log = ON;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'general_log = ON' at line 1
SELECT global.general_log;
ERROR 42S02: Unknown table 'global' in field list
SELECT general_log = @@session.general_log;
diff --git a/mysql-test/suite/sys_vars/r/identity_basic.result b/mysql-test/suite/sys_vars/r/identity_basic.result
index 40111ead253..6238f7db3b8 100644
--- a/mysql-test/suite/sys_vars/r/identity_basic.result
+++ b/mysql-test/suite/sys_vars/r/identity_basic.result
@@ -108,12 +108,8 @@ SET identity = 1;
SELECT @@identity;
@@identity
1
-SET local.identity = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'identity = 1' at line 1
SELECT local.identity;
ERROR 42S02: Unknown table 'local' in field list
-SET session.identity = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'identity = 1' at line 1
SELECT session.identity;
ERROR 42S02: Unknown table 'session' in field list
SELECT identity = @@session.identity;
diff --git a/mysql-test/suite/sys_vars/r/insert_id_basic.result b/mysql-test/suite/sys_vars/r/insert_id_basic.result
index 318563f7e42..f8ae8994120 100644
--- a/mysql-test/suite/sys_vars/r/insert_id_basic.result
+++ b/mysql-test/suite/sys_vars/r/insert_id_basic.result
@@ -108,12 +108,8 @@ SET insert_id = 1;
SELECT @@insert_id;
@@insert_id
1
-SET local.insert_id = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'insert_id = 1' at line 1
SELECT local.insert_id;
ERROR 42S02: Unknown table 'local' in field list
-SET session.insert_id = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'insert_id = 1' at line 1
SELECT session.insert_id;
ERROR 42S02: Unknown table 'session' in field list
SELECT insert_id = @@session.insert_id;
diff --git a/mysql-test/suite/sys_vars/r/key_buffer_size_basic.result b/mysql-test/suite/sys_vars/r/key_buffer_size_basic.result
index 4a63be5fd22..084e342dc2d 100644
--- a/mysql-test/suite/sys_vars/r/key_buffer_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/key_buffer_size_basic.result
@@ -62,12 +62,8 @@ SELECT @@key_buffer_size = @@global.key_buffer_size;
'#---------------------FN_DYNVARS_055_09----------------------#'
SET key_buffer_size = 8 ;
ERROR HY000: Variable 'key_buffer_size' is a GLOBAL variable and should be set with SET GLOBAL
-SET local.key_buffer_size = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size = 10' at line 1
SELECT local.key_buffer_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.key_buffer_size = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size = 10' at line 1
SELECT global.key_buffer_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT key_buffer_size = @@session.key_buffer_size;
diff --git a/mysql-test/suite/sys_vars/r/key_cache_age_threshold_basic.result b/mysql-test/suite/sys_vars/r/key_cache_age_threshold_basic.result
index f2a59e419e4..df339d7e3ab 100644
--- a/mysql-test/suite/sys_vars/r/key_cache_age_threshold_basic.result
+++ b/mysql-test/suite/sys_vars/r/key_cache_age_threshold_basic.result
@@ -115,12 +115,8 @@ ERROR HY000: Variable 'key_cache_age_threshold' is a GLOBAL variable and should
SELECT @@key_cache_age_threshold;
@@key_cache_age_threshold
100
-SET local.key_cache_age_threshold = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_age_threshold = 10' at line 1
SELECT local.key_cache_age_threshold;
ERROR 42S02: Unknown table 'local' in field list
-SET global.key_cache_age_threshold = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_age_threshold = 10' at line 1
SELECT global.key_cache_age_threshold;
ERROR 42S02: Unknown table 'global' in field list
SELECT key_cache_age_threshold = @@session.key_cache_age_threshold;
diff --git a/mysql-test/suite/sys_vars/r/key_cache_block_size_basic.result b/mysql-test/suite/sys_vars/r/key_cache_block_size_basic.result
index db8273ceed5..7271a307b7b 100644
--- a/mysql-test/suite/sys_vars/r/key_cache_block_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/key_cache_block_size_basic.result
@@ -125,12 +125,8 @@ ERROR HY000: Variable 'key_cache_block_size' is a GLOBAL variable and should be
SELECT @@key_cache_block_size;
@@key_cache_block_size
1024
-SET local.key_cache_block_size = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_block_size = 10' at line 1
SELECT local.key_cache_block_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.key_cache_block_size = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_block_size = 10' at line 1
SELECT global.key_cache_block_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT key_cache_block_size = @@session.key_cache_block_size;
diff --git a/mysql-test/suite/sys_vars/r/key_cache_division_limit_basic.result b/mysql-test/suite/sys_vars/r/key_cache_division_limit_basic.result
index 83dcea6d096..df17e92f702 100644
--- a/mysql-test/suite/sys_vars/r/key_cache_division_limit_basic.result
+++ b/mysql-test/suite/sys_vars/r/key_cache_division_limit_basic.result
@@ -119,12 +119,8 @@ ERROR HY000: Variable 'key_cache_division_limit' is a GLOBAL variable and should
SELECT @@key_cache_division_limit;
@@key_cache_division_limit
90
-SET local.key_cache_division_limit = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_division_limit = 10' at line 1
SELECT local.key_cache_division_limit;
ERROR 42S02: Unknown table 'local' in field list
-SET global.key_cache_division_limit = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_division_limit = 10' at line 1
SELECT global.key_cache_division_limit;
ERROR 42S02: Unknown table 'global' in field list
SELECT key_cache_division_limit = @@session.key_cache_division_limit;
diff --git a/mysql-test/suite/sys_vars/r/key_cache_file_hash_size_basic.result b/mysql-test/suite/sys_vars/r/key_cache_file_hash_size_basic.result
index 52ebfc98cdc..6ee871f791e 100644
--- a/mysql-test/suite/sys_vars/r/key_cache_file_hash_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/key_cache_file_hash_size_basic.result
@@ -98,12 +98,8 @@ ERROR HY000: Variable 'key_cache_file_hash_size' is a GLOBAL variable and should
SELECT @@key_cache_file_hash_size;
@@key_cache_file_hash_size
150
-SET local.key_cache_file_hash_size = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_file_hash_size = 10' at line 1
SELECT local.key_cache_file_hash_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.key_cache_file_hash_size = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_cache_file_hash_size = 10' at line 1
SELECT global.key_cache_file_hash_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT key_cache_file_hash_size = @@session.key_cache_file_hash_size;
diff --git a/mysql-test/suite/sys_vars/r/lc_time_names_basic.result b/mysql-test/suite/sys_vars/r/lc_time_names_basic.result
index ed03c3e6d94..7d98f44f27b 100644
--- a/mysql-test/suite/sys_vars/r/lc_time_names_basic.result
+++ b/mysql-test/suite/sys_vars/r/lc_time_names_basic.result
@@ -21,8 +21,6 @@ SET lc_time_names=ar_AE;
SELECT @@session.lc_time_names;
@@session.lc_time_names
ar_AE
-SET global.lc_time_names=ar_AE;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'lc_time_names=ar_AE' at line 1
SET session lc_time_names=ar_AE;
SELECT session lc_time_names;
ERROR 42S22: Unknown column 'session' in 'field list'
diff --git a/mysql-test/suite/sys_vars/r/local_infile_basic.result b/mysql-test/suite/sys_vars/r/local_infile_basic.result
index f74a394cff9..81a7a39ef21 100644
--- a/mysql-test/suite/sys_vars/r/local_infile_basic.result
+++ b/mysql-test/suite/sys_vars/r/local_infile_basic.result
@@ -87,8 +87,6 @@ ERROR HY000: Variable 'local_infile' is a GLOBAL variable and should be set with
SELECT @@local_infile;
@@local_infile
1
-SET global.local_infile = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'local_infile = 1' at line 1
SELECT global.local_infile;
ERROR 42S02: Unknown table 'global' in field list
SELECT local_infile = @@session.local_infile;
diff --git a/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic.result b/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic.result
index d6a7487c162..e84c2aa40dd 100644
--- a/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic.result
@@ -137,12 +137,8 @@ ERROR HY000: Variable 'max_binlog_cache_size' is a GLOBAL variable and should be
SELECT @@max_binlog_cache_size;
@@max_binlog_cache_size
4096
-SET local.max_binlog_cache_size = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_binlog_cache_size = 7000' at line 1
SELECT local.max_binlog_cache_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_binlog_cache_size = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_binlog_cache_size = 8000' at line 1
SELECT global.max_binlog_cache_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_binlog_cache_size = @@session.max_binlog_cache_size;
diff --git a/mysql-test/suite/sys_vars/r/max_binlog_size_basic.result b/mysql-test/suite/sys_vars/r/max_binlog_size_basic.result
index 87883351eb6..4a1e3beda67 100644
--- a/mysql-test/suite/sys_vars/r/max_binlog_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_binlog_size_basic.result
@@ -136,12 +136,8 @@ ERROR HY000: Variable 'max_binlog_size' is a GLOBAL variable and should be set w
SELECT @@max_binlog_size;
@@max_binlog_size
4096
-SET local.max_binlog_size = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_binlog_size = 7000' at line 1
SELECT local.max_binlog_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_binlog_size = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_binlog_size = 8000' at line 1
SELECT global.max_binlog_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_binlog_size = @@session.max_binlog_size;
diff --git a/mysql-test/suite/sys_vars/r/max_binlog_stmt_cache_size_basic.result b/mysql-test/suite/sys_vars/r/max_binlog_stmt_cache_size_basic.result
index 98e595cc4c3..5f4c5e3fd71 100644
--- a/mysql-test/suite/sys_vars/r/max_binlog_stmt_cache_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_binlog_stmt_cache_size_basic.result
@@ -137,12 +137,8 @@ ERROR HY000: Variable 'max_binlog_stmt_cache_size' is a GLOBAL variable and shou
SELECT @@max_binlog_stmt_cache_size;
@@max_binlog_stmt_cache_size
4096
-SET local.max_binlog_stmt_cache_size = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_binlog_stmt_cache_size = 7000' at line 1
SELECT local.max_binlog_stmt_cache_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_binlog_stmt_cache_size = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_binlog_stmt_cache_size = 8000' at line 1
SELECT global.max_binlog_stmt_cache_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_binlog_stmt_cache_size = @@session.max_binlog_stmt_cache_size;
diff --git a/mysql-test/suite/sys_vars/r/max_connect_errors_basic.result b/mysql-test/suite/sys_vars/r/max_connect_errors_basic.result
index 99bc0727ad8..01e8ef464fb 100644
--- a/mysql-test/suite/sys_vars/r/max_connect_errors_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_connect_errors_basic.result
@@ -118,12 +118,8 @@ ERROR HY000: Variable 'max_connect_errors' is a GLOBAL variable and should be se
SELECT @@max_connect_errors;
@@max_connect_errors
5000
-SET local.max_connect_errors = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_connect_errors = 7000' at line 1
SELECT local.max_connect_errors;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_connect_errors = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_connect_errors = 8000' at line 1
SELECT global.max_connect_errors;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_connect_errors = @@session.max_connect_errors;
diff --git a/mysql-test/suite/sys_vars/r/max_connections_basic.result b/mysql-test/suite/sys_vars/r/max_connections_basic.result
index 708342b016d..c215f2130c7 100644
--- a/mysql-test/suite/sys_vars/r/max_connections_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_connections_basic.result
@@ -118,12 +118,8 @@ ERROR HY000: Variable 'max_connections' is a GLOBAL variable and should be set w
SELECT @@max_connections;
@@max_connections
5000
-SET local.max_connections = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_connections = 7000' at line 1
SELECT local.max_connections;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_connections = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_connections = 8000' at line 1
SELECT global.max_connections;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_connections = @@session.max_connections;
diff --git a/mysql-test/suite/sys_vars/r/max_prepared_stmt_count_basic.result b/mysql-test/suite/sys_vars/r/max_prepared_stmt_count_basic.result
index 9419f251930..9ee2e170051 100644
--- a/mysql-test/suite/sys_vars/r/max_prepared_stmt_count_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_prepared_stmt_count_basic.result
@@ -116,12 +116,8 @@ ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should
SELECT @@max_prepared_stmt_count;
@@max_prepared_stmt_count
5000
-SET local.max_prepared_stmt_count = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_prepared_stmt_count = 7000' at line 1
SELECT local.max_prepared_stmt_count;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_prepared_stmt_count = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_prepared_stmt_count = 8000' at line 1
SELECT global.max_prepared_stmt_count;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_prepared_stmt_count = @@session.max_prepared_stmt_count;
diff --git a/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result b/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result
index 6025e28ccaa..efa2e05c59b 100644
--- a/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/max_relay_log_size_basic.result
@@ -133,12 +133,8 @@ Warning 1292 Truncated incorrect max_relay_log_size value: '6000'
SELECT @@max_relay_log_size;
@@max_relay_log_size
4096
-SET local.max_relay_log_size = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_relay_log_size = 7000' at line 1
SELECT local.max_relay_log_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.max_relay_log_size = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'max_relay_log_size = 8000' at line 1
SELECT global.max_relay_log_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT max_relay_log_size = @@session.max_relay_log_size;
diff --git a/mysql-test/suite/sys_vars/r/myisam_stats_method_basic.result b/mysql-test/suite/sys_vars/r/myisam_stats_method_basic.result
index e9150338317..19d7ba6ffb6 100644
--- a/mysql-test/suite/sys_vars/r/myisam_stats_method_basic.result
+++ b/mysql-test/suite/sys_vars/r/myisam_stats_method_basic.result
@@ -105,10 +105,6 @@ SELECT @@global.myisam_stats_method;
NULLS_UNEQUAL
'#---------------------FN_DYNVARS_097_09----------------------#'
SET myisam_stats_method = 'nulls_equal';
-SET session.myisam_stats_method = 'nulls_equal';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'myisam_stats_method = 'nulls_equal'' at line 1
-SET global.myisam_stats_method = 'nulls_equal';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'myisam_stats_method = 'nulls_equal'' at line 1
SET session myisam_stats_method = 'nulls_equal';
SELECT @@myisam_stats_method;
@@myisam_stats_method
diff --git a/mysql-test/suite/sys_vars/r/mysql56_temporal_format_basic.result b/mysql-test/suite/sys_vars/r/mysql56_temporal_format_basic.result
index 8f4500b2650..7181cba99a1 100644
--- a/mysql-test/suite/sys_vars/r/mysql56_temporal_format_basic.result
+++ b/mysql-test/suite/sys_vars/r/mysql56_temporal_format_basic.result
@@ -83,8 +83,6 @@ SELECT @@mysql56_temporal_format = @@global.mysql56_temporal_format;
'#---------------------FN_DYNVARS_030_09----------------------#'
SET mysql56_temporal_format = 1;
ERROR HY000: Variable 'mysql56_temporal_format' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.mysql56_temporal_format = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'mysql56_temporal_format = 1' at line 1
SELECT global.mysql56_temporal_format;
ERROR 42S02: Unknown table 'global' in field list
SELECT mysql56_temporal_format = @@session.mysql56_temporal_format;
diff --git a/mysql-test/suite/sys_vars/r/old_mode_basic.result b/mysql-test/suite/sys_vars/r/old_mode_basic.result
index 052221d796e..39c8e554be2 100644
--- a/mysql-test/suite/sys_vars/r/old_mode_basic.result
+++ b/mysql-test/suite/sys_vars/r/old_mode_basic.result
@@ -132,10 +132,6 @@ SELECT @@global.old_mode;
'#---------------------FN_DYNVARS_152_09----------------------#'
SET old_mode = 'NO_PROGRESS_INFO';
-SET session.old_mode = 'ANSI';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'old_mode = 'ANSI'' at line 1
-SET global.old_mode = 'ANSI';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'old_mode = 'ANSI'' at line 1
SET session old_mode = 1;
SELECT @@old_mode;
@@old_mode
diff --git a/mysql-test/suite/sys_vars/r/query_cache_limit_basic.result b/mysql-test/suite/sys_vars/r/query_cache_limit_basic.result
index 892bc306bcb..ba70a76ae55 100644
--- a/mysql-test/suite/sys_vars/r/query_cache_limit_basic.result
+++ b/mysql-test/suite/sys_vars/r/query_cache_limit_basic.result
@@ -113,12 +113,8 @@ ERROR HY000: Variable 'query_cache_limit' is a GLOBAL variable and should be set
SELECT @@query_cache_limit;
@@query_cache_limit
1
-SET local.query_cache_limit = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'query_cache_limit = 1' at line 1
SELECT local.query_cache_limit;
ERROR 42S02: Unknown table 'local' in field list
-SET global.query_cache_limit = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'query_cache_limit = 1' at line 1
SELECT global.query_cache_limit;
ERROR 42S02: Unknown table 'global' in field list
SELECT query_cache_limit = @@session.query_cache_limit;
diff --git a/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic.result b/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic.result
index bc93f966376..a46476f0fdd 100644
--- a/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic.result
+++ b/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic.result
@@ -133,12 +133,8 @@ ERROR HY000: Variable 'query_cache_min_res_unit' is a GLOBAL variable and should
SELECT @@query_cache_min_res_unit;
@@query_cache_min_res_unit
512
-SET local.query_cache_min_res_unit = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'query_cache_min_res_unit = 1' at line 1
SELECT local.query_cache_min_res_unit;
ERROR 42S02: Unknown table 'local' in field list
-SET global.query_cache_min_res_unit = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'query_cache_min_res_unit = 1' at line 1
SELECT global.query_cache_min_res_unit;
ERROR 42S02: Unknown table 'global' in field list
SELECT query_cache_min_res_unit = @@session.query_cache_min_res_unit;
diff --git a/mysql-test/suite/sys_vars/r/query_cache_size_basic.result b/mysql-test/suite/sys_vars/r/query_cache_size_basic.result
index ee959a45fa0..5d4e0a54ad9 100644
--- a/mysql-test/suite/sys_vars/r/query_cache_size_basic.result
+++ b/mysql-test/suite/sys_vars/r/query_cache_size_basic.result
@@ -120,12 +120,8 @@ ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set
SELECT @@query_cache_size;
@@query_cache_size
0
-SET local.query_cache_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'query_cache_size = 1' at line 1
SELECT local.query_cache_size;
ERROR 42S02: Unknown table 'local' in field list
-SET global.query_cache_size = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'query_cache_size = 1' at line 1
SELECT global.query_cache_size;
ERROR 42S02: Unknown table 'global' in field list
SELECT query_cache_size = @@session.query_cache_size;
diff --git a/mysql-test/suite/sys_vars/r/read_only_basic.result b/mysql-test/suite/sys_vars/r/read_only_basic.result
index 6c2c50ced46..4048e9754c4 100644
--- a/mysql-test/suite/sys_vars/r/read_only_basic.result
+++ b/mysql-test/suite/sys_vars/r/read_only_basic.result
@@ -102,12 +102,8 @@ ERROR HY000: Variable 'read_only' is a GLOBAL variable and should be set with SE
SELECT @@read_only;
@@read_only
1
-SET local.read_only = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'read_only = 1' at line 1
SELECT local.read_only;
ERROR 42S02: Unknown table 'local' in field list
-SET global.read_only = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'read_only = 1' at line 1
SELECT global.read_only;
ERROR 42S02: Unknown table 'global' in field list
SELECT read_only = @@session.read_only;
diff --git a/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result b/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result
index 8de09fe6b39..e00be57692e 100644
--- a/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result
+++ b/mysql-test/suite/sys_vars/r/relay_log_purge_basic.result
@@ -82,8 +82,6 @@ SELECT @@relay_log_purge = @@global.relay_log_purge;
'#---------------------FN_DYNVARS_141_08----------------------#'
SET relay_log_purge = 1;
ERROR HY000: Variable 'relay_log_purge' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.relay_log_purge = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'relay_log_purge = 1' at line 1
SELECT global.relay_log_purge;
ERROR 42S02: Unknown table 'global' in field list
SELECT relay_log_purge = @@session.relay_log_purge;
diff --git a/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result b/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result
index a5fe9b35ed5..9cbfb9b2c11 100644
--- a/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result
+++ b/mysql-test/suite/sys_vars/r/slave_max_allowed_packet_basic.result
@@ -131,12 +131,8 @@ ERROR HY000: Variable 'slave_max_allowed_packet' is a GLOBAL variable and should
SELECT @@slave_max_allowed_packet;
@@slave_max_allowed_packet
4096
-SET local.slave_max_allowed_packet = 7000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'slave_max_allowed_packet = 7000' at line 1
SELECT local.slave_max_allowed_packet;
ERROR 42S02: Unknown table 'local' in field list
-SET global.slave_max_allowed_packet = 8000;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'slave_max_allowed_packet = 8000' at line 1
SELECT global.slave_max_allowed_packet;
ERROR 42S02: Unknown table 'global' in field list
SELECT slave_max_allowed_packet = @@session.slave_max_allowed_packet;
diff --git a/mysql-test/suite/sys_vars/r/slow_launch_time_basic.result b/mysql-test/suite/sys_vars/r/slow_launch_time_basic.result
index e21b177eec4..3acd29b0c62 100644
--- a/mysql-test/suite/sys_vars/r/slow_launch_time_basic.result
+++ b/mysql-test/suite/sys_vars/r/slow_launch_time_basic.result
@@ -117,12 +117,8 @@ ERROR HY000: Variable 'slow_launch_time' is a GLOBAL variable and should be set
SELECT @@slow_launch_time;
@@slow_launch_time
1
-SET local.slow_launch_time = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'slow_launch_time = 1' at line 1
SELECT local.slow_launch_time;
ERROR 42S02: Unknown table 'local' in field list
-SET global.slow_launch_time = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'slow_launch_time = 1' at line 1
SELECT global.slow_launch_time;
ERROR 42S02: Unknown table 'global' in field list
SELECT slow_launch_time = @@session.slow_launch_time;
diff --git a/mysql-test/suite/sys_vars/r/slow_query_log_basic.result b/mysql-test/suite/sys_vars/r/slow_query_log_basic.result
index 049404f5648..17dfdeea3f3 100644
--- a/mysql-test/suite/sys_vars/r/slow_query_log_basic.result
+++ b/mysql-test/suite/sys_vars/r/slow_query_log_basic.result
@@ -84,12 +84,8 @@ SELECT @@slow_query_log = @@global.slow_query_log;
@@slow_query_log = @@global.slow_query_log
0
'#---------------------FN_DYNVARS_004_09----------------------#'
-SET local.slow_query_log = OFF;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'slow_query_log = OFF' at line 1
SELECT local.slow_query_log;
ERROR 42S02: Unknown table 'local' in field list
-SET global.slow_query_log = ON;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'slow_query_log = ON' at line 1
SELECT global.slow_query_log;
ERROR 42S02: Unknown table 'global' in field list
SELECT slow_query_log = @@session.slow_query_log;
diff --git a/mysql-test/suite/sys_vars/r/sql_mode_basic.result b/mysql-test/suite/sys_vars/r/sql_mode_basic.result
index 2e3ca45d4f5..1bd35c0656f 100644
--- a/mysql-test/suite/sys_vars/r/sql_mode_basic.result
+++ b/mysql-test/suite/sys_vars/r/sql_mode_basic.result
@@ -381,10 +381,6 @@ SELECT @@global.sql_mode;
'#---------------------FN_DYNVARS_152_09----------------------#'
SET sql_mode = 'ANSI';
-SET session.sql_mode = 'ANSI';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sql_mode = 'ANSI'' at line 1
-SET global.sql_mode = 'ANSI';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sql_mode = 'ANSI'' at line 1
SET session sql_mode = 1;
SELECT @@sql_mode;
@@sql_mode
diff --git a/mysql-test/suite/sys_vars/r/sync_binlog_basic.result b/mysql-test/suite/sys_vars/r/sync_binlog_basic.result
index bb0c8136391..cb0af255f33 100644
--- a/mysql-test/suite/sys_vars/r/sync_binlog_basic.result
+++ b/mysql-test/suite/sys_vars/r/sync_binlog_basic.result
@@ -98,12 +98,8 @@ ERROR HY000: Variable 'sync_binlog' is a GLOBAL variable and should be set with
SELECT @@sync_binlog;
@@sync_binlog
4294967295
-SET local.sync_binlog = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sync_binlog = 1' at line 1
SELECT local.sync_binlog;
ERROR 42S02: Unknown table 'local' in field list
-SET global.sync_binlog = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sync_binlog = 1' at line 1
SELECT global.sync_binlog;
ERROR 42S02: Unknown table 'global' in field list
SELECT sync_binlog = @@session.sync_binlog;
diff --git a/mysql-test/suite/sys_vars/r/sync_frm_basic.result b/mysql-test/suite/sys_vars/r/sync_frm_basic.result
index 0c633d30820..ce9d0a1f358 100644
--- a/mysql-test/suite/sys_vars/r/sync_frm_basic.result
+++ b/mysql-test/suite/sys_vars/r/sync_frm_basic.result
@@ -85,8 +85,6 @@ ERROR HY000: Variable 'sync_frm' is a GLOBAL variable and should be set with SET
SELECT @@sync_frm;
@@sync_frm
1
-SET global.sync_frm = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'sync_frm = 1' at line 1
SELECT global.sync_frm;
ERROR 42S02: Unknown table 'global' in field list
SELECT sync_frm = @@session.sync_frm;
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 7cc9fe3c44a..fa09c33cc9a 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2867,9 +2867,9 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
SESSION_VALUE NULL
-GLOBAL_VALUE 188
+GLOBAL_VALUE 191
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE 188
+DEFAULT_VALUE 191
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments.
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 6e36a67b96a..af17ac34b61 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -3063,9 +3063,9 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES
SESSION_VALUE NULL
-GLOBAL_VALUE 188
+GLOBAL_VALUE 191
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE 188
+DEFAULT_VALUE 191
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Maximum number of statement instruments.
diff --git a/mysql-test/suite/sys_vars/r/table_definition_cache_basic.result b/mysql-test/suite/sys_vars/r/table_definition_cache_basic.result
index f6befe51bc1..54b50c5ff75 100644
--- a/mysql-test/suite/sys_vars/r/table_definition_cache_basic.result
+++ b/mysql-test/suite/sys_vars/r/table_definition_cache_basic.result
@@ -99,8 +99,6 @@ SELECT @@table_definition_cache = @@global.table_definition_cache;
'#---------------------FN_DYNVARS_019_09----------------------#'
SET table_definition_cache = 1;
ERROR HY000: Variable 'table_definition_cache' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.table_definition_cache = 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'table_definition_cache = 1' at line 1
SELECT global.table_definition_cache;
ERROR 42S02: Unknown table 'global' in field list
SELECT table_definition_cache = @@session.table_definition_cache;
diff --git a/mysql-test/suite/sys_vars/r/table_open_cache_basic.result b/mysql-test/suite/sys_vars/r/table_open_cache_basic.result
index 4c635783753..4e9190e022d 100644
--- a/mysql-test/suite/sys_vars/r/table_open_cache_basic.result
+++ b/mysql-test/suite/sys_vars/r/table_open_cache_basic.result
@@ -95,8 +95,6 @@ SELECT @@table_open_cache = @@global.table_open_cache ;
'#---------------------FN_DYNVARS_001_11----------------------#'
SET table_open_cache = 8;
ERROR HY000: Variable 'table_open_cache' is a GLOBAL variable and should be set with SET GLOBAL
-SET global.table_open_cache = 10;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'table_open_cache = 10' at line 1
SELECT global.table_open_cache ;
ERROR 42S02: Unknown table 'global' in field list
SELECT table_open_cache = @@session.table_open_cache ;
diff --git a/mysql-test/suite/sys_vars/r/tx_isolation_basic.result b/mysql-test/suite/sys_vars/r/tx_isolation_basic.result
index 09ccebf12a2..f6ee2c92fa5 100644
--- a/mysql-test/suite/sys_vars/r/tx_isolation_basic.result
+++ b/mysql-test/suite/sys_vars/r/tx_isolation_basic.result
@@ -123,10 +123,6 @@ SELECT @@global.tx_isolation;
READ-UNCOMMITTED
'#---------------------FN_DYNVARS_183_09----------------------#'
SET tx_isolation = 'REPEATABLE-READ';
-SET session.tx_isolation = 'REPEATABLE-READ';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'tx_isolation = 'REPEATABLE-READ'' at line 1
-SET global.tx_isolation = 'REPEATABLE-READ';
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'tx_isolation = 'REPEATABLE-READ'' at line 1
SET session tx_isolation = 'REPEATABLE-READ';
SELECT @@tx_isolation;
@@tx_isolation
diff --git a/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test b/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test
index dfa733a0b9b..6f7ceed0437 100644
--- a/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test
+++ b/mysql-test/suite/sys_vars/t/automatic_sp_privileges_basic.test
@@ -152,12 +152,8 @@ SELECT @@automatic_sp_privileges = @@global.automatic_sp_privileges;
###############################################################################
--Error ER_GLOBAL_VARIABLE
SET automatic_sp_privileges = 1;
---Error ER_PARSE_ERROR
-SET local.automatic_sp_privileges = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.automatic_sp_privileges;
---Error ER_PARSE_ERROR
-SET global.automatic_sp_privileges = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.automatic_sp_privileges;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/big_tables_basic.test b/mysql-test/suite/sys_vars/t/big_tables_basic.test
index 89a7ee83bc8..d004feac3db 100644
--- a/mysql-test/suite/sys_vars/t/big_tables_basic.test
+++ b/mysql-test/suite/sys_vars/t/big_tables_basic.test
@@ -148,12 +148,8 @@ SELECT @@big_tables = @@local.big_tables and @@local.big_tables = @@session.big_
SET big_tables = 1;
SELECT @@big_tables;
---Error ER_PARSE_ERROR
-SET local.big_tables = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.big_tables;
---Error ER_PARSE_ERROR
-SET session.big_tables = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.big_tables;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/binlog_cache_size_basic.test b/mysql-test/suite/sys_vars/t/binlog_cache_size_basic.test
index 57822ef0b48..da098fc3495 100644
--- a/mysql-test/suite/sys_vars/t/binlog_cache_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/binlog_cache_size_basic.test
@@ -134,8 +134,6 @@ SELECT @@binlog_cache_size = @@global.binlog_cache_size;
--Error ER_GLOBAL_VARIABLE
SET binlog_cache_size = 1;
---Error ER_PARSE_ERROR
-SET global.binlog_cache_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.binlog_cache_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/binlog_stmt_cache_size_basic.test b/mysql-test/suite/sys_vars/t/binlog_stmt_cache_size_basic.test
index ecde1723c11..5c74c6fe8fe 100644
--- a/mysql-test/suite/sys_vars/t/binlog_stmt_cache_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/binlog_stmt_cache_size_basic.test
@@ -134,8 +134,6 @@ SELECT @@binlog_stmt_cache_size = @@global.binlog_stmt_cache_size;
--Error ER_GLOBAL_VARIABLE
SET binlog_stmt_cache_size = 1;
---Error ER_PARSE_ERROR
-SET global.binlog_stmt_cache_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.binlog_stmt_cache_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/bulk_insert_buffer_size_basic.test b/mysql-test/suite/sys_vars/t/bulk_insert_buffer_size_basic.test
index 5796db32565..125dc2fcf58 100644
--- a/mysql-test/suite/sys_vars/t/bulk_insert_buffer_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/bulk_insert_buffer_size_basic.test
@@ -181,12 +181,8 @@ SELECT @@local.bulk_insert_buffer_size = @@session.bulk_insert_buffer_size;
SET bulk_insert_buffer_size = 1;
SELECT @@bulk_insert_buffer_size;
---Error ER_PARSE_ERROR
-SET local.bulk_insert_buffer_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.bulk_insert_buffer_size;
---Error ER_PARSE_ERROR
-SET session.bulk_insert_buffer_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.bulk_insert_buffer_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/character_set_client_basic.test b/mysql-test/suite/sys_vars/t/character_set_client_basic.test
index 7b3d36fb16f..d8ae6a81444 100644
--- a/mysql-test/suite/sys_vars/t/character_set_client_basic.test
+++ b/mysql-test/suite/sys_vars/t/character_set_client_basic.test
@@ -62,8 +62,6 @@ SELECT character_set_client;
SET character_set_client=utf8;
SELECT @@session.character_set_client;
# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.character_set_client=utf8;
# using another syntax for accessing session variable
SET session character_set_client=utf8;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/character_set_connection_basic.test b/mysql-test/suite/sys_vars/t/character_set_connection_basic.test
index e402dbb0ff5..bb63ff8db6a 100644
--- a/mysql-test/suite/sys_vars/t/character_set_connection_basic.test
+++ b/mysql-test/suite/sys_vars/t/character_set_connection_basic.test
@@ -62,8 +62,6 @@ SELECT character_set_connection;
SET character_set_connection=utf8;
SELECT @@session.character_set_connection;
# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.character_set_connection=utf8;
# using another syntax for accessing session variable
SET session character_set_connection=utf8;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/character_set_database_basic.test b/mysql-test/suite/sys_vars/t/character_set_database_basic.test
index 4e650dc6139..f3a1ee45de0 100644
--- a/mysql-test/suite/sys_vars/t/character_set_database_basic.test
+++ b/mysql-test/suite/sys_vars/t/character_set_database_basic.test
@@ -62,8 +62,6 @@ SELECT character_set_database;
SET character_set_database=utf8;
SELECT @@session.character_set_database;
# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.character_set_database=utf8;
# using another syntax for accessing session variable
SET session character_set_database=utf8;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/character_set_filesystem_basic.test b/mysql-test/suite/sys_vars/t/character_set_filesystem_basic.test
index 6bb2de35429..33b77eede06 100644
--- a/mysql-test/suite/sys_vars/t/character_set_filesystem_basic.test
+++ b/mysql-test/suite/sys_vars/t/character_set_filesystem_basic.test
@@ -62,9 +62,6 @@ SELECT character_set_filesystem;
# assign value without @@
SET character_set_filesystem=utf8;
SELECT @@session.character_set_filesystem;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.character_set_filesystem=utf8;
# using another syntax for accessing session variable
SET session character_set_filesystem=utf8;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/character_set_results_basic.test b/mysql-test/suite/sys_vars/t/character_set_results_basic.test
index 1bede9e493c..5472cd1509e 100644
--- a/mysql-test/suite/sys_vars/t/character_set_results_basic.test
+++ b/mysql-test/suite/sys_vars/t/character_set_results_basic.test
@@ -61,9 +61,6 @@ SELECT character_set_results;
# assign value without @@
SET character_set_results=utf8;
SELECT @@session.character_set_results;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.character_set_results=utf8;
# using another syntax for accessing session variable
SET session character_set_results=utf8;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/character_set_server_basic.test b/mysql-test/suite/sys_vars/t/character_set_server_basic.test
index d692c1f633c..adb80fcfffd 100644
--- a/mysql-test/suite/sys_vars/t/character_set_server_basic.test
+++ b/mysql-test/suite/sys_vars/t/character_set_server_basic.test
@@ -59,9 +59,6 @@ SELECT character_set_server;
# assign value without @@
SET character_set_server=utf8;
SELECT @@session.character_set_server;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.character_set_server=utf8;
# using another syntax for accessing session variable
SET session character_set_server=utf8;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/collation_connection_basic.test b/mysql-test/suite/sys_vars/t/collation_connection_basic.test
index 92f1766fc9c..963eadbbcbd 100644
--- a/mysql-test/suite/sys_vars/t/collation_connection_basic.test
+++ b/mysql-test/suite/sys_vars/t/collation_connection_basic.test
@@ -59,9 +59,6 @@ SELECT collation_connection;
# assign value without @@
SET collation_connection=utf8_unicode_ci;
SELECT @@session.collation_connection;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.collation_connection=utf8_unicode_ci;
# using another syntax for accessing session variable
SET session collation_connection=utf8_unicode_ci;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/collation_database_basic.test b/mysql-test/suite/sys_vars/t/collation_database_basic.test
index da06778bb68..04aee789746 100644
--- a/mysql-test/suite/sys_vars/t/collation_database_basic.test
+++ b/mysql-test/suite/sys_vars/t/collation_database_basic.test
@@ -59,9 +59,6 @@ SELECT collation_database;
# assign value without @@
SET collation_database=utf8_unicode_ci;
SELECT @@session.collation_database;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.collation_database=utf8_unicode_ci;
# using another syntax for accessing session variable
SET session collation_database=utf8_unicode_ci;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/collation_server_basic.test b/mysql-test/suite/sys_vars/t/collation_server_basic.test
index 0d01c7d3076..b8c2a25fc46 100644
--- a/mysql-test/suite/sys_vars/t/collation_server_basic.test
+++ b/mysql-test/suite/sys_vars/t/collation_server_basic.test
@@ -59,9 +59,6 @@ SELECT collation_server;
# assign value without @@
SET collation_server=utf8_unicode_ci;
SELECT @@session.collation_server;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.collation_server=utf8_unicode_ci;
# using another syntax for accessing session variable
SET session collation_server=utf8_unicode_ci;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/completion_type_basic.test b/mysql-test/suite/sys_vars/t/completion_type_basic.test
index 927654cd32a..7a962fbdf99 100644
--- a/mysql-test/suite/sys_vars/t/completion_type_basic.test
+++ b/mysql-test/suite/sys_vars/t/completion_type_basic.test
@@ -157,12 +157,8 @@ SELECT @@local.completion_type = @@session.completion_type;
SET completion_type = 1;
SELECT @@completion_type;
---Error ER_PARSE_ERROR
-SET local.completion_type = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.completion_type;
---Error ER_PARSE_ERROR
-SET session.completion_type = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.completion_type;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/concurrent_insert_basic.test b/mysql-test/suite/sys_vars/t/concurrent_insert_basic.test
index 5be569e52d3..6f08915079a 100644
--- a/mysql-test/suite/sys_vars/t/concurrent_insert_basic.test
+++ b/mysql-test/suite/sys_vars/t/concurrent_insert_basic.test
@@ -164,8 +164,6 @@ SELECT @@concurrent_insert = @@global.concurrent_insert;
--Error ER_GLOBAL_VARIABLE
SET concurrent_insert = 1;
SELECT @@concurrent_insert;
---Error ER_PARSE_ERROR
-SET global.concurrent_insert = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.concurrent_insert;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/connect_timeout_basic.test b/mysql-test/suite/sys_vars/t/connect_timeout_basic.test
index d89734a00c2..b20006e5c96 100644
--- a/mysql-test/suite/sys_vars/t/connect_timeout_basic.test
+++ b/mysql-test/suite/sys_vars/t/connect_timeout_basic.test
@@ -131,8 +131,6 @@ SELECT @@connect_timeout = @@global.connect_timeout;
--Error ER_GLOBAL_VARIABLE
SET connect_timeout = 1;
---Error ER_PARSE_ERROR
-SET global.connect_timeout = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.connect_timeout;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/default_master_connection_basic.test b/mysql-test/suite/sys_vars/t/default_master_connection_basic.test
index 627a236aaa7..ae91bc46e1a 100644
--- a/mysql-test/suite/sys_vars/t/default_master_connection_basic.test
+++ b/mysql-test/suite/sys_vars/t/default_master_connection_basic.test
@@ -102,12 +102,8 @@ SELECT @@local.default_master_connection = @@session.default_master_connection;
SET default_master_connection = 'foo';
SELECT @@default_master_connection;
---Error ER_PARSE_ERROR
-SET local.default_master_connection = 'foo';
--Error ER_UNKNOWN_TABLE
SELECT local.default_master_connection;
---Error ER_PARSE_ERROR
-SET session.default_master_connection = 'foo';
--Error ER_UNKNOWN_TABLE
SELECT session.default_master_connection;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/default_week_format_basic.test b/mysql-test/suite/sys_vars/t/default_week_format_basic.test
index e609cdc53f5..592379bae8c 100644
--- a/mysql-test/suite/sys_vars/t/default_week_format_basic.test
+++ b/mysql-test/suite/sys_vars/t/default_week_format_basic.test
@@ -170,12 +170,8 @@ SELECT @@local.default_week_format = @@session.default_week_format;
SET default_week_format = 1;
SELECT @@default_week_format;
---Error ER_PARSE_ERROR
-SET local.default_week_format = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.default_week_format;
---Error ER_PARSE_ERROR
-SET session.default_week_format = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.default_week_format;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/delayed_insert_limit_basic.test b/mysql-test/suite/sys_vars/t/delayed_insert_limit_basic.test
index 0c9a7d1ddb8..3eb345dc5c3 100644
--- a/mysql-test/suite/sys_vars/t/delayed_insert_limit_basic.test
+++ b/mysql-test/suite/sys_vars/t/delayed_insert_limit_basic.test
@@ -141,12 +141,8 @@ SELECT @@delayed_insert_limit = @@global.delayed_insert_limit;
--Error ER_GLOBAL_VARIABLE
SET delayed_insert_limit = 1;
SELECT @@delayed_insert_limit;
---Error ER_PARSE_ERROR
-SET local.delayed_insert_limit = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.delayed_insert_limit;
---Error ER_PARSE_ERROR
-SET global.delayed_insert_limit = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.delayed_insert_limit;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/delayed_insert_timeout_basic.test b/mysql-test/suite/sys_vars/t/delayed_insert_timeout_basic.test
index 2486ff5800f..79521924290 100644
--- a/mysql-test/suite/sys_vars/t/delayed_insert_timeout_basic.test
+++ b/mysql-test/suite/sys_vars/t/delayed_insert_timeout_basic.test
@@ -140,12 +140,8 @@ SELECT @@delayed_insert_timeout = @@global.delayed_insert_timeout;
--Error 1229
SET delayed_insert_timeout = 1;
SELECT @@delayed_insert_timeout;
---Error 1064
-SET local.delayed_insert_timeout = 1;
--Error 1109
SELECT local.delayed_insert_timeout;
---Error 1064
-SET global.delayed_insert_timeout = 1;
--Error 1109
SELECT global.delayed_insert_timeout;
--Error 1054
diff --git a/mysql-test/suite/sys_vars/t/delayed_queue_size_basic.test b/mysql-test/suite/sys_vars/t/delayed_queue_size_basic.test
index e8b5ab31224..a0aae63c8b8 100644
--- a/mysql-test/suite/sys_vars/t/delayed_queue_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/delayed_queue_size_basic.test
@@ -136,12 +136,8 @@ SELECT @@delayed_queue_size = @@global.delayed_queue_size;
--Error 1229
SET delayed_queue_size = 1;
SELECT @@delayed_queue_size;
---Error ER_PARSE_ERROR
-SET local.delayed_queue_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.delayed_queue_size;
---Error ER_PARSE_ERROR
-SET global.delayed_queue_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.delayed_queue_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/div_precision_increment_basic.test b/mysql-test/suite/sys_vars/t/div_precision_increment_basic.test
index 97f0e0eab81..6399288cafc 100644
--- a/mysql-test/suite/sys_vars/t/div_precision_increment_basic.test
+++ b/mysql-test/suite/sys_vars/t/div_precision_increment_basic.test
@@ -179,12 +179,8 @@ SELECT @@local.div_precision_increment = @@session.div_precision_increment;
SET div_precision_increment = 1;
SELECT @@div_precision_increment;
---Error ER_PARSE_ERROR
-SET local.div_precision_increment = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.div_precision_increment;
---Error ER_PARSE_ERROR
-SET session.div_precision_increment = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.div_precision_increment;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/event_scheduler_basic.test b/mysql-test/suite/sys_vars/t/event_scheduler_basic.test
index 2e6aa3cba5c..acd7d4bd8a8 100644
--- a/mysql-test/suite/sys_vars/t/event_scheduler_basic.test
+++ b/mysql-test/suite/sys_vars/t/event_scheduler_basic.test
@@ -147,12 +147,8 @@ SELECT @@event_scheduler = @@global.event_scheduler;
#######################################################################
--Error ER_GLOBAL_VARIABLE
SET event_scheduler = ON;
---Error ER_PARSE_ERROR
-SET local.event_scheduler = OFF;
--Error ER_UNKNOWN_TABLE
SELECT local.event_scheduler;
---Error ER_PARSE_ERROR
-SET global.event_scheduler = ON;
--Error ER_UNKNOWN_TABLE
SELECT global.event_scheduler;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/expire_logs_days_basic.test b/mysql-test/suite/sys_vars/t/expire_logs_days_basic.test
index f19ab922c72..fa57cec38c6 100644
--- a/mysql-test/suite/sys_vars/t/expire_logs_days_basic.test
+++ b/mysql-test/suite/sys_vars/t/expire_logs_days_basic.test
@@ -153,12 +153,8 @@ SELECT @@expire_logs_days = @@global.expire_logs_days;
--Error ER_GLOBAL_VARIABLE
SET expire_logs_days = 1;
SELECT @@expire_logs_days;
---Error ER_PARSE_ERROR
-SET local.expire_logs_days = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.expire_logs_days;
---Error ER_PARSE_ERROR
-SET global.expire_logs_days = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.expire_logs_days;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/flush_basic.test b/mysql-test/suite/sys_vars/t/flush_basic.test
index 4eb821e9af1..842d0caa581 100644
--- a/mysql-test/suite/sys_vars/t/flush_basic.test
+++ b/mysql-test/suite/sys_vars/t/flush_basic.test
@@ -149,8 +149,6 @@ SELECT @@flush = @@global.flush;
--Error ER_GLOBAL_VARIABLE
SET flush = 1;
---Error ER_PARSE_ERROR
-SET global.flush = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.flush;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/general_log_basic.test b/mysql-test/suite/sys_vars/t/general_log_basic.test
index 6a1d00f1b6f..b41185e2049 100644
--- a/mysql-test/suite/sys_vars/t/general_log_basic.test
+++ b/mysql-test/suite/sys_vars/t/general_log_basic.test
@@ -143,12 +143,8 @@ SELECT @@general_log = @@global.general_log;
#######################################################################
--Error ER_GLOBAL_VARIABLE
SET general_log = ON;
---Error ER_PARSE_ERROR
-SET local.general_log = OFF;
--Error ER_UNKNOWN_TABLE
SELECT local.general_log;
---Error ER_PARSE_ERROR
-SET global.general_log = ON;
--Error ER_UNKNOWN_TABLE
SELECT global.general_log;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/identity_basic.test b/mysql-test/suite/sys_vars/t/identity_basic.test
index 2ddec32a621..f88d2651046 100644
--- a/mysql-test/suite/sys_vars/t/identity_basic.test
+++ b/mysql-test/suite/sys_vars/t/identity_basic.test
@@ -163,12 +163,8 @@ SELECT @@session.identity = @@local.identity;
SET identity = 1;
SELECT @@identity;
---Error ER_PARSE_ERROR
-SET local.identity = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.identity;
---Error ER_PARSE_ERROR
-SET session.identity = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.identity;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/insert_id_basic.test b/mysql-test/suite/sys_vars/t/insert_id_basic.test
index c9d3e1f4e52..36272e99617 100644
--- a/mysql-test/suite/sys_vars/t/insert_id_basic.test
+++ b/mysql-test/suite/sys_vars/t/insert_id_basic.test
@@ -164,12 +164,8 @@ SELECT @@session.insert_id = @@local.insert_id;
SET insert_id = 1;
SELECT @@insert_id;
---Error ER_PARSE_ERROR
-SET local.insert_id = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.insert_id;
---Error ER_PARSE_ERROR
-SET session.insert_id = 1;
--Error ER_UNKNOWN_TABLE
SELECT session.insert_id;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/key_buffer_size_basic.test b/mysql-test/suite/sys_vars/t/key_buffer_size_basic.test
index 354c65490a4..a737b30ac97 100644
--- a/mysql-test/suite/sys_vars/t/key_buffer_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/key_buffer_size_basic.test
@@ -128,12 +128,8 @@ SELECT @@key_buffer_size = @@global.key_buffer_size;
--Error ER_GLOBAL_VARIABLE
SET key_buffer_size = 8 ;
---Error ER_PARSE_ERROR
-SET local.key_buffer_size = 10;
--Error ER_UNKNOWN_TABLE
SELECT local.key_buffer_size;
---Error ER_PARSE_ERROR
-SET global.key_buffer_size = 10;
--Error ER_UNKNOWN_TABLE
SELECT global.key_buffer_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/key_cache_age_threshold_basic.test b/mysql-test/suite/sys_vars/t/key_cache_age_threshold_basic.test
index e0970016577..0d47dc3f613 100644
--- a/mysql-test/suite/sys_vars/t/key_cache_age_threshold_basic.test
+++ b/mysql-test/suite/sys_vars/t/key_cache_age_threshold_basic.test
@@ -148,12 +148,8 @@ SELECT @@key_cache_age_threshold = @@global.key_cache_age_threshold;
--Error ER_GLOBAL_VARIABLE
SET key_cache_age_threshold = 8000;
SELECT @@key_cache_age_threshold;
---Error ER_PARSE_ERROR
-SET local.key_cache_age_threshold = 10;
--Error ER_UNKNOWN_TABLE
SELECT local.key_cache_age_threshold;
---Error ER_PARSE_ERROR
-SET global.key_cache_age_threshold = 10;
--Error ER_UNKNOWN_TABLE
SELECT global.key_cache_age_threshold;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/key_cache_block_size_basic.test b/mysql-test/suite/sys_vars/t/key_cache_block_size_basic.test
index 99a3c5dc327..6e84b121dbd 100644
--- a/mysql-test/suite/sys_vars/t/key_cache_block_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/key_cache_block_size_basic.test
@@ -152,12 +152,8 @@ SELECT @@key_cache_block_size = @@global.key_cache_block_size;
--Error ER_GLOBAL_VARIABLE
SET key_cache_block_size = 8000;
SELECT @@key_cache_block_size;
---Error ER_PARSE_ERROR
-SET local.key_cache_block_size = 10;
--Error ER_UNKNOWN_TABLE
SELECT local.key_cache_block_size;
---Error ER_PARSE_ERROR
-SET global.key_cache_block_size = 10;
--Error ER_UNKNOWN_TABLE
SELECT global.key_cache_block_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/key_cache_division_limit_basic.test b/mysql-test/suite/sys_vars/t/key_cache_division_limit_basic.test
index dd41e4d37a0..a1770d62e57 100644
--- a/mysql-test/suite/sys_vars/t/key_cache_division_limit_basic.test
+++ b/mysql-test/suite/sys_vars/t/key_cache_division_limit_basic.test
@@ -153,12 +153,8 @@ SELECT @@key_cache_division_limit = @@global.key_cache_division_limit;
--Error ER_GLOBAL_VARIABLE
SET key_cache_division_limit = 80;
SELECT @@key_cache_division_limit;
---Error ER_PARSE_ERROR
-SET local.key_cache_division_limit = 10;
--Error ER_UNKNOWN_TABLE
SELECT local.key_cache_division_limit;
---Error ER_PARSE_ERROR
-SET global.key_cache_division_limit = 10;
--Error ER_UNKNOWN_TABLE
SELECT global.key_cache_division_limit;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/key_cache_file_hash_size_basic.test b/mysql-test/suite/sys_vars/t/key_cache_file_hash_size_basic.test
index deebe708d3d..b8caa5bbf70 100644
--- a/mysql-test/suite/sys_vars/t/key_cache_file_hash_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/key_cache_file_hash_size_basic.test
@@ -143,12 +143,8 @@ SELECT @@key_cache_file_hash_size = @@global.key_cache_file_hash_size;
--Error ER_GLOBAL_VARIABLE
SET key_cache_file_hash_size = 8000;
SELECT @@key_cache_file_hash_size;
---Error ER_PARSE_ERROR
-SET local.key_cache_file_hash_size = 10;
--Error ER_UNKNOWN_TABLE
SELECT local.key_cache_file_hash_size;
---Error ER_PARSE_ERROR
-SET global.key_cache_file_hash_size = 10;
--Error ER_UNKNOWN_TABLE
SELECT global.key_cache_file_hash_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/lc_time_names_basic.test b/mysql-test/suite/sys_vars/t/lc_time_names_basic.test
index c66bdc40a02..7f748bec2c0 100644
--- a/mysql-test/suite/sys_vars/t/lc_time_names_basic.test
+++ b/mysql-test/suite/sys_vars/t/lc_time_names_basic.test
@@ -56,9 +56,6 @@ SELECT lc_time_names;
# assign value without @@
SET lc_time_names=ar_AE;
SELECT @@session.lc_time_names;
-# assign global variable without @@
---Error ER_PARSE_ERROR
-SET global.lc_time_names=ar_AE;
# using another syntax for accessing session variable
SET session lc_time_names=ar_AE;
# accessing variable with scope the wrong way
diff --git a/mysql-test/suite/sys_vars/t/local_infile_basic.test b/mysql-test/suite/sys_vars/t/local_infile_basic.test
index 731eac42541..4430fa32f0a 100644
--- a/mysql-test/suite/sys_vars/t/local_infile_basic.test
+++ b/mysql-test/suite/sys_vars/t/local_infile_basic.test
@@ -154,8 +154,6 @@ SELECT @@local_infile = @@global.local_infile;
--Error ER_GLOBAL_VARIABLE
SET local_infile = 1;
SELECT @@local_infile;
---Error ER_PARSE_ERROR
-SET global.local_infile = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.local_infile;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_binlog_cache_size_basic.test b/mysql-test/suite/sys_vars/t/max_binlog_cache_size_basic.test
index 710299f053c..974ec95ca5c 100644
--- a/mysql-test/suite/sys_vars/t/max_binlog_cache_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_binlog_cache_size_basic.test
@@ -165,12 +165,8 @@ SELECT @@max_binlog_cache_size = @@global.max_binlog_cache_size;
--Error ER_GLOBAL_VARIABLE
SET max_binlog_cache_size = 6000;
SELECT @@max_binlog_cache_size;
---Error ER_PARSE_ERROR
-SET local.max_binlog_cache_size = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_binlog_cache_size;
---Error ER_PARSE_ERROR
-SET global.max_binlog_cache_size = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_binlog_cache_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_binlog_size_basic.test b/mysql-test/suite/sys_vars/t/max_binlog_size_basic.test
index 4d2574a7890..22e8808ed8c 100644
--- a/mysql-test/suite/sys_vars/t/max_binlog_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_binlog_size_basic.test
@@ -153,12 +153,8 @@ SELECT @@max_binlog_size = @@global.max_binlog_size;
--Error ER_GLOBAL_VARIABLE
SET max_binlog_size = 6000;
SELECT @@max_binlog_size;
---Error ER_PARSE_ERROR
-SET local.max_binlog_size = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_binlog_size;
---Error ER_PARSE_ERROR
-SET global.max_binlog_size = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_binlog_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_binlog_stmt_cache_size_basic.test b/mysql-test/suite/sys_vars/t/max_binlog_stmt_cache_size_basic.test
index 3c2f6f6d391..ba528e268ec 100644
--- a/mysql-test/suite/sys_vars/t/max_binlog_stmt_cache_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_binlog_stmt_cache_size_basic.test
@@ -166,12 +166,8 @@ SELECT @@max_binlog_stmt_cache_size = @@global.max_binlog_stmt_cache_size;
--Error ER_GLOBAL_VARIABLE
SET max_binlog_stmt_cache_size = 6000;
SELECT @@max_binlog_stmt_cache_size;
---Error ER_PARSE_ERROR
-SET local.max_binlog_stmt_cache_size = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_binlog_stmt_cache_size;
---Error ER_PARSE_ERROR
-SET global.max_binlog_stmt_cache_size = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_binlog_stmt_cache_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_connect_errors_basic.test b/mysql-test/suite/sys_vars/t/max_connect_errors_basic.test
index ffad23f6ba7..cc860e92fbb 100644
--- a/mysql-test/suite/sys_vars/t/max_connect_errors_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_connect_errors_basic.test
@@ -152,12 +152,8 @@ SELECT @@max_connect_errors = @@global.max_connect_errors;
--Error ER_GLOBAL_VARIABLE
SET max_connect_errors = 6000;
SELECT @@max_connect_errors;
---Error ER_PARSE_ERROR
-SET local.max_connect_errors = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_connect_errors;
---Error ER_PARSE_ERROR
-SET global.max_connect_errors = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_connect_errors;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_connections_basic.test b/mysql-test/suite/sys_vars/t/max_connections_basic.test
index 346f7d8f460..de259b32c17 100644
--- a/mysql-test/suite/sys_vars/t/max_connections_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_connections_basic.test
@@ -153,12 +153,8 @@ SELECT @@max_connections = @@global.max_connections;
--Error ER_GLOBAL_VARIABLE
SET max_connections = 6000;
SELECT @@max_connections;
---Error ER_PARSE_ERROR
-SET local.max_connections = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_connections;
---Error ER_PARSE_ERROR
-SET global.max_connections = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_connections;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_prepared_stmt_count_basic.test b/mysql-test/suite/sys_vars/t/max_prepared_stmt_count_basic.test
index 5bf5d9c8834..a1961a61a40 100644
--- a/mysql-test/suite/sys_vars/t/max_prepared_stmt_count_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_prepared_stmt_count_basic.test
@@ -158,12 +158,8 @@ SELECT @@max_prepared_stmt_count = @@global.max_prepared_stmt_count;
--Error ER_GLOBAL_VARIABLE
SET max_prepared_stmt_count = 6000;
SELECT @@max_prepared_stmt_count;
---Error ER_PARSE_ERROR
-SET local.max_prepared_stmt_count = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_prepared_stmt_count;
---Error ER_PARSE_ERROR
-SET global.max_prepared_stmt_count = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_prepared_stmt_count;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test b/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test
index 05d0fd1be82..de7cc395daf 100644
--- a/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/max_relay_log_size_basic.test
@@ -150,12 +150,8 @@ SELECT @@max_relay_log_size = @@global.max_relay_log_size;
SET max_relay_log_size = 6000;
SELECT @@max_relay_log_size;
---Error ER_PARSE_ERROR
-SET local.max_relay_log_size = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.max_relay_log_size;
---Error ER_PARSE_ERROR
-SET global.max_relay_log_size = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.max_relay_log_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/myisam_stats_method_basic.test b/mysql-test/suite/sys_vars/t/myisam_stats_method_basic.test
index f70431b5580..6fecee3f32d 100644
--- a/mysql-test/suite/sys_vars/t/myisam_stats_method_basic.test
+++ b/mysql-test/suite/sys_vars/t/myisam_stats_method_basic.test
@@ -178,11 +178,6 @@ SELECT @@global.myisam_stats_method;
SET myisam_stats_method = 'nulls_equal';
---Error ER_PARSE_ERROR
-SET session.myisam_stats_method = 'nulls_equal';
---Error ER_PARSE_ERROR
-SET global.myisam_stats_method = 'nulls_equal';
-
SET session myisam_stats_method = 'nulls_equal';
SELECT @@myisam_stats_method;
diff --git a/mysql-test/suite/sys_vars/t/mysql56_temporal_format_basic.test b/mysql-test/suite/sys_vars/t/mysql56_temporal_format_basic.test
index d0de9202d3f..f6def41fa56 100644
--- a/mysql-test/suite/sys_vars/t/mysql56_temporal_format_basic.test
+++ b/mysql-test/suite/sys_vars/t/mysql56_temporal_format_basic.test
@@ -144,8 +144,6 @@ SELECT @@mysql56_temporal_format = @@global.mysql56_temporal_format;
--Error ER_GLOBAL_VARIABLE
SET mysql56_temporal_format = 1;
---Error ER_PARSE_ERROR
-SET global.mysql56_temporal_format = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.mysql56_temporal_format;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/old_mode_basic.test b/mysql-test/suite/sys_vars/t/old_mode_basic.test
index 93a93960836..088f85c48bd 100644
--- a/mysql-test/suite/sys_vars/t/old_mode_basic.test
+++ b/mysql-test/suite/sys_vars/t/old_mode_basic.test
@@ -197,11 +197,6 @@ SELECT @@global.old_mode;
SET old_mode = 'NO_PROGRESS_INFO';
---Error ER_PARSE_ERROR
-SET session.old_mode = 'ANSI';
---Error ER_PARSE_ERROR
-SET global.old_mode = 'ANSI';
-
SET session old_mode = 1;
SELECT @@old_mode;
diff --git a/mysql-test/suite/sys_vars/t/query_cache_limit_basic.test b/mysql-test/suite/sys_vars/t/query_cache_limit_basic.test
index c94ba3a52dd..98baa17d421 100644
--- a/mysql-test/suite/sys_vars/t/query_cache_limit_basic.test
+++ b/mysql-test/suite/sys_vars/t/query_cache_limit_basic.test
@@ -152,12 +152,8 @@ SELECT @@query_cache_limit = @@global.query_cache_limit;
--Error ER_GLOBAL_VARIABLE
SET query_cache_limit = 1;
SELECT @@query_cache_limit;
---Error ER_PARSE_ERROR
-SET local.query_cache_limit = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.query_cache_limit;
---Error ER_PARSE_ERROR
-SET global.query_cache_limit = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.query_cache_limit;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/query_cache_min_res_unit_basic.test b/mysql-test/suite/sys_vars/t/query_cache_min_res_unit_basic.test
index 9276a987dfb..b7916e73fa2 100644
--- a/mysql-test/suite/sys_vars/t/query_cache_min_res_unit_basic.test
+++ b/mysql-test/suite/sys_vars/t/query_cache_min_res_unit_basic.test
@@ -159,12 +159,8 @@ SELECT @@query_cache_min_res_unit = @@global.query_cache_min_res_unit;
--Error ER_GLOBAL_VARIABLE
SET query_cache_min_res_unit = 1;
SELECT @@query_cache_min_res_unit;
---Error ER_PARSE_ERROR
-SET local.query_cache_min_res_unit = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.query_cache_min_res_unit;
---Error ER_PARSE_ERROR
-SET global.query_cache_min_res_unit = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.query_cache_min_res_unit;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/query_cache_size_basic.test b/mysql-test/suite/sys_vars/t/query_cache_size_basic.test
index 2a589ae3771..352cc29a445 100644
--- a/mysql-test/suite/sys_vars/t/query_cache_size_basic.test
+++ b/mysql-test/suite/sys_vars/t/query_cache_size_basic.test
@@ -142,12 +142,8 @@ SELECT @@query_cache_size = @@global.query_cache_size;
--Error ER_GLOBAL_VARIABLE
SET query_cache_size = 1;
SELECT @@query_cache_size;
---Error ER_PARSE_ERROR
-SET local.query_cache_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.query_cache_size;
---Error ER_PARSE_ERROR
-SET global.query_cache_size = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.query_cache_size;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/read_only_basic.test b/mysql-test/suite/sys_vars/t/read_only_basic.test
index 0f77e983f92..3ef35020f01 100644
--- a/mysql-test/suite/sys_vars/t/read_only_basic.test
+++ b/mysql-test/suite/sys_vars/t/read_only_basic.test
@@ -146,12 +146,8 @@ SELECT @@read_only = @@global.read_only;
--Error ER_GLOBAL_VARIABLE
SET read_only = 1;
SELECT @@read_only;
---Error ER_PARSE_ERROR
-SET local.read_only = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.read_only;
---Error ER_PARSE_ERROR
-SET global.read_only = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.read_only;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test b/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test
index 081b79ebb73..dd211bb10ea 100644
--- a/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test
+++ b/mysql-test/suite/sys_vars/t/relay_log_purge_basic.test
@@ -143,8 +143,6 @@ SELECT @@relay_log_purge = @@global.relay_log_purge;
--Error ER_GLOBAL_VARIABLE
SET relay_log_purge = 1;
---Error ER_PARSE_ERROR
-SET global.relay_log_purge = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.relay_log_purge;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test b/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test
index 4caaae84906..821c1855b03 100644
--- a/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test
+++ b/mysql-test/suite/sys_vars/t/slave_max_allowed_packet_basic.test
@@ -152,12 +152,8 @@ SELECT @@slave_max_allowed_packet = @@global.slave_max_allowed_packet;
--Error ER_GLOBAL_VARIABLE
SET slave_max_allowed_packet = 6000;
SELECT @@slave_max_allowed_packet;
---Error ER_PARSE_ERROR
-SET local.slave_max_allowed_packet = 7000;
--Error ER_UNKNOWN_TABLE
SELECT local.slave_max_allowed_packet;
---Error ER_PARSE_ERROR
-SET global.slave_max_allowed_packet = 8000;
--Error ER_UNKNOWN_TABLE
SELECT global.slave_max_allowed_packet;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/slow_launch_time_basic.test b/mysql-test/suite/sys_vars/t/slow_launch_time_basic.test
index bedcb6201b1..71b25185549 100644
--- a/mysql-test/suite/sys_vars/t/slow_launch_time_basic.test
+++ b/mysql-test/suite/sys_vars/t/slow_launch_time_basic.test
@@ -151,12 +151,8 @@ SELECT @@slow_launch_time = @@global.slow_launch_time;
--Error ER_GLOBAL_VARIABLE
SET slow_launch_time = 1;
SELECT @@slow_launch_time;
---Error ER_PARSE_ERROR
-SET local.slow_launch_time = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.slow_launch_time;
---Error ER_PARSE_ERROR
-SET global.slow_launch_time = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.slow_launch_time;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/slow_query_log_basic.test b/mysql-test/suite/sys_vars/t/slow_query_log_basic.test
index b429f9f5cea..3d58902ab8d 100644
--- a/mysql-test/suite/sys_vars/t/slow_query_log_basic.test
+++ b/mysql-test/suite/sys_vars/t/slow_query_log_basic.test
@@ -145,12 +145,8 @@ SELECT @@slow_query_log = @@global.slow_query_log;
######################################################################
# Check if slow_query_log can be accessed with and without @@ sign #
######################################################################
---Error ER_PARSE_ERROR
-SET local.slow_query_log = OFF;
--Error ER_UNKNOWN_TABLE
SELECT local.slow_query_log;
---Error ER_PARSE_ERROR
-SET global.slow_query_log = ON;
--Error ER_UNKNOWN_TABLE
SELECT global.slow_query_log;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/sql_mode_basic.test b/mysql-test/suite/sys_vars/t/sql_mode_basic.test
index 83f938925d5..ad1c722303c 100644
--- a/mysql-test/suite/sys_vars/t/sql_mode_basic.test
+++ b/mysql-test/suite/sys_vars/t/sql_mode_basic.test
@@ -336,11 +336,6 @@ SELECT @@global.sql_mode;
SET sql_mode = 'ANSI';
---Error ER_PARSE_ERROR
-SET session.sql_mode = 'ANSI';
---Error ER_PARSE_ERROR
-SET global.sql_mode = 'ANSI';
-
SET session sql_mode = 1;
SELECT @@sql_mode;
diff --git a/mysql-test/suite/sys_vars/t/sync_binlog_basic.test b/mysql-test/suite/sys_vars/t/sync_binlog_basic.test
index 71a35a30c58..5b7c5f37191 100644
--- a/mysql-test/suite/sys_vars/t/sync_binlog_basic.test
+++ b/mysql-test/suite/sys_vars/t/sync_binlog_basic.test
@@ -131,12 +131,8 @@ WHERE VARIABLE_NAME='sync_binlog';
--Error ER_GLOBAL_VARIABLE
SET sync_binlog = 1;
SELECT @@sync_binlog;
---Error ER_PARSE_ERROR
-SET local.sync_binlog = 1;
--Error ER_UNKNOWN_TABLE
SELECT local.sync_binlog;
---Error ER_PARSE_ERROR
-SET global.sync_binlog = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.sync_binlog;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/sync_frm_basic.test b/mysql-test/suite/sys_vars/t/sync_frm_basic.test
index d9dcffb6318..6fb9e03d572 100644
--- a/mysql-test/suite/sys_vars/t/sync_frm_basic.test
+++ b/mysql-test/suite/sys_vars/t/sync_frm_basic.test
@@ -144,8 +144,6 @@ SELECT @@sync_frm = @@global.sync_frm;
--Error ER_GLOBAL_VARIABLE
SET sync_frm = 1;
SELECT @@sync_frm;
---Error ER_PARSE_ERROR
-SET global.sync_frm = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.sync_frm;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/table_definition_cache_basic.test b/mysql-test/suite/sys_vars/t/table_definition_cache_basic.test
index 69f29108645..dc0903c5d40 100644
--- a/mysql-test/suite/sys_vars/t/table_definition_cache_basic.test
+++ b/mysql-test/suite/sys_vars/t/table_definition_cache_basic.test
@@ -137,8 +137,6 @@ SELECT @@table_definition_cache = @@global.table_definition_cache;
--Error ER_GLOBAL_VARIABLE
SET table_definition_cache = 1;
---Error ER_PARSE_ERROR
-SET global.table_definition_cache = 1;
--Error ER_UNKNOWN_TABLE
SELECT global.table_definition_cache;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/table_open_cache_basic.test b/mysql-test/suite/sys_vars/t/table_open_cache_basic.test
index 7d2549cd87f..d2450e9586e 100644
--- a/mysql-test/suite/sys_vars/t/table_open_cache_basic.test
+++ b/mysql-test/suite/sys_vars/t/table_open_cache_basic.test
@@ -152,8 +152,6 @@ SELECT @@table_open_cache = @@global.table_open_cache ;
--Error ER_GLOBAL_VARIABLE
SET table_open_cache = 8;
---Error ER_PARSE_ERROR
-SET global.table_open_cache = 10;
--Error ER_UNKNOWN_TABLE
SELECT global.table_open_cache ;
--Error ER_BAD_FIELD_ERROR
diff --git a/mysql-test/suite/sys_vars/t/tx_isolation_basic.test b/mysql-test/suite/sys_vars/t/tx_isolation_basic.test
index 0a15aa08b6b..5b484cb9b1b 100644
--- a/mysql-test/suite/sys_vars/t/tx_isolation_basic.test
+++ b/mysql-test/suite/sys_vars/t/tx_isolation_basic.test
@@ -189,10 +189,6 @@ SELECT @@global.tx_isolation;
SET tx_isolation = 'REPEATABLE-READ';
---Error ER_PARSE_ERROR
-SET session.tx_isolation = 'REPEATABLE-READ';
---Error ER_PARSE_ERROR
-SET global.tx_isolation = 'REPEATABLE-READ';
#using SET SESSION|GLOBAL syntax
SET session tx_isolation = 'REPEATABLE-READ';
SELECT @@tx_isolation;
diff --git a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result
index 9413dbdace7..dd767071dc9 100644
--- a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result
@@ -915,7 +915,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
`b` varchar(10) DEFAULT NULL,
- `c` varchar(20) GENERATED ALWAYS AS (insert(`a`,length(`a`),length(`b`),`b`)) VIRTUAL
+ `c` varchar(20) GENERATED ALWAYS AS (insert(`a`,octet_length(`a`),octet_length(`b`),`b`)) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ('start,','end',default);
select * from t1;
@@ -978,7 +978,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) GENERATED ALWAYS AS (length(`a`)) VIRTUAL
+ `b` int(11) GENERATED ALWAYS AS (octet_length(`a`)) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ('text',default);
select * from t1;
@@ -1142,7 +1142,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(10) DEFAULT NULL,
- `b` int(11) GENERATED ALWAYS AS (length(`a`)) VIRTUAL
+ `b` int(11) GENERATED ALWAYS AS (octet_length(`a`)) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values ('text',default);
select * from t1;
diff --git a/mysql-test/suite/vcol/r/vcol_view_innodb.result b/mysql-test/suite/vcol/r/vcol_view_innodb.result
index 091cdc02fb3..b5d722f4d58 100644
--- a/mysql-test/suite/vcol/r/vcol_view_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_view_innodb.result
@@ -35,7 +35,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
+Note 1003 /* select#1 */ select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
create view v3 (d,e) as select d*2, e*2 from v1;
select * from v3;
d e
diff --git a/mysql-test/suite/vcol/r/vcol_view_myisam.result b/mysql-test/suite/vcol/r/vcol_view_myisam.result
index 8ad1853faa4..8f86774c418 100644
--- a/mysql-test/suite/vcol/r/vcol_view_myisam.result
+++ b/mysql-test/suite/vcol/r/vcol_view_myisam.result
@@ -35,7 +35,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
-Note 1003 select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
+Note 1003 /* select#1 */ select `v2`.`d` AS `d`,`v2`.`e` AS `e` from `test`.`v2`
create view v3 (d,e) as select d*2, e*2 from v1;
select * from v3;
d e
diff --git a/mysql-test/t/bug13633383.test b/mysql-test/t/bug13633383.test
index e31d4a8c9f6..29106d379fe 100644
--- a/mysql-test/t/bug13633383.test
+++ b/mysql-test/t/bug13633383.test
@@ -67,6 +67,7 @@ INSERT INTO t3 VALUES (4294967296,'2011-04-12 21:05:37',0x0000CE3238,'xwcplgaxcp
--enable_query_log
set session sort_buffer_size= 32768;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
select col435
from t3
natural right outer join t1
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index 7cc74c52b28..87f12cd9e38 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -275,3 +275,58 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 test
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
+--echo #
+
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT
+ CASE -1
+ WHEN -9223372036854775808 THEN 'one'
+ WHEN 18446744073709551615 THEN 'two'
+ END AS c;
+
+PREPARE stmt FROM "SELECT
+ CASE -1
+ WHEN -9223372036854775808 THEN 'one'
+ WHEN 18446744073709551615 THEN 'two'
+ END AS c";
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
+--echo #
+SELECT
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ END AS good,
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
+ END AS was_bad_now_good;
+
+PREPARE stmt FROM "SELECT
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ END AS good,
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
+ END AS was_bad_now_good";
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index d62612f819e..17e8be839a8 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -514,3 +514,76 @@ CREATE TABLE t1 AS SELECT
CONCAT(CONVERT('',UNSIGNED));
SHOW CREATE TABLE t1;
DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12849 Out-of-range errors when casting hex-hybrid to SIGNED and UNSIGNED
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+DELIMITER $$;
+CREATE PROCEDURE p1(hh TEXT)
+BEGIN
+ EXECUTE IMMEDIATE
+ CONCAT('CREATE OR REPLACE TABLE t1 AS SELECT CAST(0x', hh, ' AS UNSIGNED) AS c');
+ DESCRIBE t1;
+ SELECT c, LENGTH(c) FROM t1;
+ DROP TABLE t1;
+ EXECUTE IMMEDIATE
+ CONCAT('CREATE OR REPLACE TABLE t1 AS SELECT CAST(0x', hh, ' AS SIGNED) AS c');
+ DESCRIBE t1;
+ SELECT c, LENGTH(c) FROM t1;
+ DROP TABLE t1;
+ SELECT '' AS `------`;
+END
+$$
+DELIMITER ;$$
+CALL p1('FF');
+CALL p1('FFFF');
+CALL p1('FFFFFF');
+CALL p1('FFFFFFFF');
+CALL p1('FFFFFFFFFF');
+CALL p1('FFFFFFFFFFFF');
+CALL p1('FFFFFFFFFFFFFF');
+CALL p1('FFFFFFFFFFFFFFFF');
+CALL p1('FFFFFFFFFFFFFFFFFF');
+CALL p1('FFFFFFFFFFFFFFFFFFFF');
+
+CALL p1('8000000000000000');
+CALL p1('80000000000000FF');
+CALL p1('800000000000FFFF');
+CALL p1('8000000000FFFFFF');
+CALL p1('80000000FFFFFFFF');
+CALL p1('800000FFFFFFFFFF');
+CALL p1('8000FFFFFFFFFFFF');
+CALL p1('80FFFFFFFFFFFFFF');
+CALL p1('8FFFFFFFFFFFFFFF');
+
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-12852 Out-of-range errors when CAST(1-2 AS UNSIGNED
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT
+ CAST(-1 AS UNSIGNED),
+ CAST(1-2 AS UNSIGNED);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-12853 Out-of-range errors when CAST('-1' AS UNSIGNED
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT CAST('-1' AS UNSIGNED);
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 6461204f06e..bd89f220060 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -402,6 +402,22 @@ explain t2;
select * from t2;
drop table t1, t2;
+CREATE TABLE t1 (
+ c_tinytext tinytext,
+ c_text text,
+ c_mediumtext mediumtext,
+ c_longtext longtext
+);
+CREATE TABLE t2 AS SELECT
+ ifnull(c_tinytext, CAST('yet another binary data' AS BINARY)),
+ ifnull(c_text, CAST('yet another binary data' AS BINARY)),
+ ifnull(c_mediumtext, CAST('yet another binary data' AS BINARY)),
+ ifnull(c_longtext, CAST('yet another binary data' AS BINARY))
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10));
create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnull(e,e), ifnull(f,f), ifnull(g,g), ifnull(h,h), ifnull(i,i), ifnull(j,j), ifnull(k,k), ifnull(l,l), ifnull(m,m), ifnull(n,n), ifnull(o,o) from t1;
show create table t2;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index d1fe93d9251..b191b27d367 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -2095,3 +2095,32 @@ let $coll_pad='utf8_bin';
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+
+--echo #
+--echo # MDEV-11155 Bad error message when creating a SET column with comma and non-ASCII characters
+--echo #
+
+SET NAMES utf8;
+--error ER_ILLEGAL_VALUE_FOR_TYPE
+CREATE TABLE t1 (a SET('a,bü'));
+
+--echo #
+--echo # MDEV-12607 Hybrid functions create wrong VARBINARY length when mixing character and binary data
+--echo #
+SET sql_mode='';
+SET NAMES utf8;
+CREATE OR REPLACE TABLE t1 AS SELECT COALESCE('ßa',_binary 'a');
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test
index 84ef620de04..a3b349bb384 100644
--- a/mysql-test/t/default.test
+++ b/mysql-test/t/default.test
@@ -795,11 +795,9 @@ DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(30,6) DEFAULT COALESCE(CURRENT_TIMESTAMP(6)));
SHOW CREATE TABLE t1;
-# Same as insert into t1 values ("2016-06-05 12:54:52.342095");
INSERT INTO t1 VALUES();
INSERT IGNORE INTO t1 VALUES();
SET sql_mode = 'STRICT_ALL_TABLES';
---error WARN_DATA_TRUNCATED
INSERT INTO t1 VALUES();
SET sql_mode = DEFAULT;
DROP TABLE t1;
diff --git a/mysql-test/t/delete_use_source.test b/mysql-test/t/delete_use_source.test
new file mode 100644
index 00000000000..a54d12c3d65
--- /dev/null
+++ b/mysql-test/t/delete_use_source.test
@@ -0,0 +1,132 @@
+--source include/have_sequence.inc
+--source include/have_innodb.inc
+create table t1(c1 integer not null,c2 integer not null, key (c1)) engine=InnoDb;
+create view v1 as select * from t1 where c1 in (0,1);
+
+insert t1 select 0,seq from seq_1_to_500;
+insert t1 select 1,seq from seq_1_to_50;
+insert t1 select 2,seq from seq_1_to_20;
+insert t1 select 3,seq from seq_1_to_20;
+
+--echo #
+--echo # Delete with limit (quick select - range acces)
+--echo #
+
+start transaction;
+--enable_info
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
+--disable_info
+select count(*) from v1 where c1=0;
+rollback;
+
+--echo #
+--echo # Delete
+--echo #
+
+start transaction;
+--enable_info ONCE
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 ;
+rollback;
+
+--echo #
+--echo # Delete with exists
+--echo #
+
+start transaction;
+select count(*) from v1 where c1=2;
+--enable_info
+delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
+delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
+--disable_info
+select count(*) from v1 where c1=2;
+rollback;
+
+--echo #
+--echo # Delete throw a view with limit (range access)
+--echo #
+
+start transaction;
+explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
+--enable_info
+delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
+delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
+--disable_info
+select count(*) from v1 where c1=0;
+rollback;
+
+--echo #
+--echo # Delete throw a view (ALL access)
+--echo #
+
+start transaction;
+explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500;
+--enable_info ONCE
+delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ;
+select count(*) from v1 where c1=0;
+rollback;
+
+--echo #
+--echo # Delete failed due to trigger
+--echo #
+
+delimiter /;
+create trigger trg after delete on t1 for each row
+begin
+ declare c int;
+ begin
+ if old.c1 = 1 then
+ select count(*) into c from t1 where c1!=old.c1;
+ SIGNAL SQLSTATE '45000' set table_name=c;
+ end if;
+ end;
+end;
+/
+delimiter ;/
+
+start transaction;
+--error ER_SIGNAL_EXCEPTION
+delete from t1 where c1=1 and (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c2 asc limit 10;
+rollback;
+start transaction;
+--error ER_SIGNAL_EXCEPTION
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c1 desc limit 100;
+select c1,count(*) from t1 group by c1;
+rollback;
+
+drop trigger trg;
+
+--echo #
+--echo # Delete throw a view with returning
+--echo #
+
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 asc limit 10 returning c1,c2;
+rollback;
+start transaction;
+delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 desc limit 10 returning c1,c2;
+rollback;
+
+drop view v1;
+drop table t1;
+
+--echo #
+--echo # Delete from table with more than 150000 rows
+--echo #
+create table t1(c1 integer not null,c2 integer not null, key (c1));
+insert t1 select 0,seq from seq_1_to_128000;
+insert t1 select 1,seq from seq_1_to_25600;
+select count(*) from t1;
+
+--echo # with a lot of memory for sort_buffer_size
+set session sort_buffer_size = 1024000;
+--enable_info ONCE
+delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
+
+--echo # with little memory for sort_buffer_size
+insert t1 select 0,seq from seq_1_to_128000;
+set session sort_buffer_size = 1024;
+--enable_info ONCE
+delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
+
+drop table t1;
diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test
index a3e96953bac..6f506dd7215 100644
--- a/mysql-test/t/drop.test
+++ b/mysql-test/t/drop.test
@@ -288,7 +288,7 @@ DROP TABLE t1;
DROP TABLE table1;
--error ER_BAD_TABLE_ERROR
DROP TABLE table1,table2;
---error ER_BAD_TABLE_ERROR
+--error ER_UNKNOWN_VIEW
DROP VIEW view1,view2,view3,view4;
--echo
DROP TABLE IF EXISTS table1;
diff --git a/mysql-test/t/except.test b/mysql-test/t/except.test
new file mode 100644
index 00000000000..e13137701a9
--- /dev/null
+++ b/mysql-test/t/except.test
@@ -0,0 +1,83 @@
+create table t1 (a int, b int) engine=MyISAM;
+create table t2 (c int, d int) engine=MyISAM;
+insert into t1 values (1,1),(2,2);
+insert into t2 values (2,2),(3,3);
+
+(select a,b from t1) except (select c,d from t2);
+EXPLAIN (select a,b from t1) except (select c,d from t2);
+EXPLAIN extended (select a,b from t1) except (select c,d from t2);
+EXPLAIN extended select * from ((select a,b from t1) except (select c,d from t2)) a;
+EXPLAIN format=json (select a,b from t1) except (select c,d from t2);
+
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json (select a,b from t1) except (select c,d from t2);
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json select * from ((select a,b from t1) except (select c,d from t2)) a;
+select * from ((select a,b from t1) except (select c,d from t2)) a;
+
+prepare stmt from "(select a,b from t1) except (select c,d from t2)";
+execute stmt;
+execute stmt;
+
+prepare stmt from "select * from ((select a,b from t1) except (select c,d from t2)) a";
+execute stmt;
+execute stmt;
+
+drop tables t1,t2;
+
+
+create table t1 (a int, b int) engine=MyISAM;
+create table t2 (c int, d int) engine=MyISAM;
+create table t3 (e int, f int) engine=MyISAM;
+create table t4 (g int, h int) engine=MyISAM;
+insert into t1 values (1,1),(2,2);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (4,4),(5,5);
+insert into t4 values (4,4),(7,7);
+
+(select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+EXPLAIN (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+EXPLAIN (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+EXPLAIN extended select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a;
+EXPLAIN format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4);
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json select * from ((select a,b,e,f from t1,t3) except
+(select c,d,g,h from t2,t4)) a;
+select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a;
+
+prepare stmt from "(select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)";
+execute stmt;
+execute stmt;
+
+prepare stmt from "select * from ((select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4)) a";
+execute stmt;
+execute stmt;
+
+drop tables t1,t2,t3,t4;
+
+select 1 as a from dual except select 1 from dual;
+(select 1 from dual) except (select 1 from dual);
+--error ER_WRONG_USAGE
+(select 1 from dual into @v) except (select 1 from dual);
+--error ER_PARSE_ERROR
+select 1 from dual ORDER BY 1 except select 1 from dual;
+
+select 1 as a from dual union all select 1 from dual;
+--error ER_WRONG_USAGE
+select 1 from dual except all select 1 from dual;
+
+
+create table t1 (a int, b blob, a1 int, b1 blob) engine=MyISAM;
+create table t2 (c int, d blob, c1 int, d1 blob) engine=MyISAM;
+insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt");
+insert into t2 values (2, "fgh", 2, "dffggtt"),(3, "ffggddd", 3, "dfgg");
+
+(select a,b,b1 from t1) except (select c,d,d1 from t2);
+# make sure that blob is used
+create table t3 (select a,b,b1 from t1) except (select c,d,d1 from t2);
+show create table t3;
+
+drop tables t1,t2,t3;
diff --git a/mysql-test/t/func_debug.test b/mysql-test/t/func_debug.test
new file mode 100644
index 00000000000..e0960f736cb
--- /dev/null
+++ b/mysql-test/t/func_debug.test
@@ -0,0 +1,477 @@
+--source include/have_debug.inc
+
+SET SESSION debug_dbug="+d,Item_func_in";
+SET SESSION debug_dbug="+d,Predicant_to_list_comparator";
+
+--echo # Constant predicant, compatible types, bisect
+SELECT 1 IN (1,2);
+SELECT 1 IN (1,2,NULL);
+SELECT 1 NOT IN (1,2);
+SELECT 1 NOT IN (1,2,NULL);
+
+SELECT 1.0 IN (1.0,2.0);
+SELECT 1.0 IN (1.0,2.0,NULL);
+SELECT 1.0 NOT IN (1.0,2.0);
+SELECT 1.0 NOT IN (1.0,2.0,NULL);
+
+SELECT 1e0 IN (1e0,2e0);
+SELECT 1e0 IN (1e0,2e0,NULL);
+SELECT 1e0 NOT IN (1e0,2e0);
+SELECT 1e0 NOT IN (1e0,2e0,NULL);
+
+SELECT 'a' IN ('a','b');
+SELECT 'a' IN ('a','b',NULL);
+SELECT 'a' NOT IN ('a','b');
+SELECT 'a' NOT IN ('a','b',NULL);
+
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30');
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL);
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30');
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN ('2001-01-01 10:20:30','2001-02-02 10:20:30',NULL);
+
+SELECT TIME'10:20:30' IN ('10:20:30','10:20:30');
+SELECT TIME'10:20:30' IN ('10:20:30','10:20:30',NULL);
+SELECT TIME'10:20:30' NOT IN ('10:20:30','10:20:30');
+SELECT TIME'10:20:30' NOT IN ('10:20:30','10:20:30',NULL);
+
+SELECT DATE'2001-01-01' IN ('2001-01-01','2001-02-02');
+SELECT DATE'2001-01-01' IN ('2001-01-01','2001-02-02',NULL);
+SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02');
+SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02',NULL);
+
+
+--echo # Column predicant, compatible types, bisect
+
+# Special case: mixture of unsigned, signed and decimal
+CREATE TABLE t1 (a INT UNSIGNED);
+# a=1.0 is done as decimal, because decimal bits int
+# a=1 is done as decimal as well, because of different unsigned flag
+SELECT a IN (1.0, 1) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT);
+SELECT a IN (1,2,3) FROM t1;
+SELECT a IN (1,2,3,NULL) FROM t1;
+SELECT a IN (1.0, CAST(1 AS UNSIGNED)) FROM t1;
+SELECT a IN (1.0, CAST(1 AS UNSIGNED),NULL) FROM t1;
+SELECT a NOT IN (1,2,3) FROM t1;
+SELECT a NOT IN (1,2,3,NULL) FROM t1;
+SELECT a NOT IN (1.0, CAST(1 AS UNSIGNED)) FROM t1;
+SELECT a NOT IN (1.0, CAST(1 AS UNSIGNED),NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DOUBLE);
+SELECT a IN (1e0,2,3.0) FROM t1;
+SELECT a IN (1e0,2,3.0,NULL) FROM t1;
+SELECT a NOT IN (1e0,2,3.0) FROM t1;
+SELECT a NOT IN (1e0,2,3.0,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DECIMAL(10,1));
+SELECT a IN (1,2.0,3.0) FROM t1;
+SELECT a IN (1,2.0,3.0,NULL) FROM t1;
+SELECT a NOT IN (1,2.0,3.0) FROM t1;
+SELECT a NOT IN (1,2.0,3.0,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10));
+SELECT a IN ('a','b','c') FROM t1;
+SELECT a IN ('a','b','c',NULL) FROM t1;
+SELECT a NOT IN ('a','b','c') FROM t1;
+SELECT a NOT IN ('a','b','c',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATE);
+SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1;
+SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1;
+SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1;
+SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TIME);
+SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1;
+SELECT a IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1;
+SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0) FROM t1;
+SELECT a NOT IN ('10:20:30',TIME'10:20:30',102030,102030.0,102030e0,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATETIME);
+SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1;
+SELECT a IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1;
+SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0) FROM t1;
+SELECT a NOT IN ('2001-01-01',TIMESTAMP'2001-01-01 10:20:30',DATE'2001-01-01',TIME'10:20:30',20010101102030,20010101102030.0,20010101102030e0,NULL) FROM t1;
+DROP TABLE t1;
+
+--echo # Constant predicant, compatible types, no bisect
+--echo # Bisect is not used because of non-constant expressions in the list
+CREATE TABLE t1 (a INT);
+SELECT 1 IN (a,1,2,3) FROM t1;
+SELECT 1 IN (a,1,2,3,NULL) FROM t1;
+SELECT 1 NOT IN (a,1,2,3) FROM t1;
+SELECT 1 NOT IN (a,1,2,3,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DOUBLE);
+SELECT 1 IN (a,1e0,2e0,3e0) FROM t1;
+SELECT 1 IN (a,1e0,2e0,3e0,NULL) FROM t1;
+SELECT 1 NOT IN (a,1e0,2e0,3e0) FROM t1;
+SELECT 1 NOT IN (a,1e0,2e0,3e0,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DECIMAL(10,1));
+SELECT 1 IN (a,1.0,2.0,3.0) FROM t1;
+SELECT 1 IN (a,1.0,2.0,3.0,NULL) FROM t1;
+SELECT 1 NOT IN (a,1.0,2.0,3.0) FROM t1;
+SELECT 1 NOT IN (a,1.0,2.0,3.0,NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10));
+SELECT 'a' IN (a,'b','c') FROM t1;
+SELECT 'a' IN (a,'b','c',NULL) FROM t1;
+SELECT 'a' NOT IN (a,'b','c') FROM t1;
+SELECT 'a' NOT IN (a,'b','c',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATE);
+SELECT DATE'2001-01-01' IN (a,'2001-01-01') FROM t1;
+SELECT DATE'2001-01-01' IN (a,'2001-01-01',NULL) FROM t1;
+SELECT DATE'2001-01-01' NOT IN (a,'2001-01-01') FROM t1;
+SELECT DATE'2001-01-01' NOT IN (a,'2001-01-01',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TIME);
+SELECT TIME'10:20:30' IN (a,'10:20:30') FROM t1;
+SELECT TIME'10:20:30' IN (a,'10:20:30',NULL) FROM t1;
+SELECT TIME'10:20:30' NOT IN (a,'10:20:30') FROM t1;
+SELECT TIME'10:20:30' NOT IN (a,'10:20:30',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATETIME);
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+SELECT TIMESTAMP'2001-01-01 10:20:30' IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+SELECT TIMESTAMP'2001-01-01 10:20:30' NOT IN (a,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+DROP TABLE t1;
+
+
+--echo # Constant predicant, incompatible types, no bisect
+SELECT 1 IN (1,2e0);
+SELECT 1 IN (1,2e0,NULL);
+SELECT 1 NOT IN (1,2e0);
+SELECT 1 NOT IN (1,2e0,NULL);
+
+SELECT 1.0 IN (1.0,2e0);
+SELECT 1.0 IN (1.0,2e0,NULL);
+SELECT 1.0 NOT IN (1.0,2e0);
+SELECT 1.0 NOT IN (1.0,2e0,NULL);
+
+SELECT 1e0 IN (1.0,TIME'10:20:30');
+SELECT 1e0 IN (1.0,TIME'10:20:30',NULL);
+SELECT 1e0 NOT IN (1.0,TIME'10:20:30');
+SELECT 1e0 NOT IN (1.0,TIME'10:20:30',NULL);
+
+SELECT 'a' IN ('a',2);
+SELECT 'a' IN ('a',2,NULL);
+SELECT 'a' NOT IN ('a',2);
+SELECT 'a' NOT IN ('a',2,NULL);
+
+SELECT TIME'10:20:30' IN (1,TIME'10:20:30');
+SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL);
+SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30');
+SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL);
+SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
+SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
+
+--echo # Column predicant, incompatible types, no bisect
+CREATE TABLE t1 (a INT);
+SELECT a IN (1,1e0) FROM t1;
+SELECT a IN (1,1e0,NULL) FROM t1;
+SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+SELECT a NOT IN (1,1e0) FROM t1;
+SELECT a NOT IN (1,1e0,NULL) FROM t1;
+SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
+SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
+
+SELECT a IN (1,1.0) FROM t1;
+SELECT a IN (1,1.0,NULL) FROM t1;
+SELECT a NOT IN (1,1.0) FROM t1;
+SELECT a NOT IN (1,1.0,NULL) FROM t1;
+
+SELECT a IN (1,'1') FROM t1;
+SELECT a IN (1,'1',NULL) FROM t1;
+SELECT a NOT IN (1,'1') FROM t1;
+SELECT a NOT IN (1,'1',NULL) FROM t1;
+
+SELECT a IN (1,TIME'10:20:30') FROM t1;
+SELECT a IN (1,TIME'10:20:30',NULL) FROM t1;
+SELECT a NOT IN (1,TIME'10:20:30') FROM t1;
+SELECT a NOT IN (1,TIME'10:20:30',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DECIMAL(10,0));
+SELECT a IN (1,1e0) FROM t1;
+SELECT a IN (1,1e0,NULL) FROM t1;
+SELECT a NOT IN (1,1e0) FROM t1;
+SELECT a NOT IN (1,1e0,NULL) FROM t1;
+
+SELECT a IN (1,'1') FROM t1;
+SELECT a IN (1,'1',NULL) FROM t1;
+SELECT a NOT IN (1,'1') FROM t1;
+SELECT a NOT IN (1,'1',NULL) FROM t1;
+
+SELECT a IN (1,TIME'10:20:30') FROM t1;
+SELECT a IN (1,TIME'10:20:30',NULL) FROM t1;
+SELECT a NOT IN (1,TIME'10:20:30') FROM t1;
+SELECT a NOT IN (1,TIME'10:20:30',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DOUBLE);
+SELECT a IN (1,TIME'10:20:30') FROM t1;
+SELECT a IN (1,TIME'10:20:30',NULL) FROM t1;
+SELECT a NOT IN (1,TIME'10:20:30') FROM t1;
+SELECT a NOT IN (1,TIME'10:20:30',NULL) FROM t1;
+
+SELECT a IN (1,DATE'2001-01-01') FROM t1;
+SELECT a IN (1,DATE'2001-01-01',NULL) FROM t1;
+SELECT a NOT IN (1,DATE'2001-01-01') FROM t1;
+SELECT a NOT IN (1,DATE'2001-01-01',NULL) FROM t1;
+
+SELECT a IN (1,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+SELECT a IN (1,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+SELECT a NOT IN (1,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
+SELECT a NOT IN (1,TIMESTAMP'2001-01-01 10:20:30',NULL) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(10));
+SELECT a IN ('a',1) FROM t1;
+SELECT a IN ('a',TIME'10:20:30') FROM t1;
+SELECT a NOT IN ('a',1) FROM t1;
+SELECT a NOT IN ('a',TIME'10:20:30') FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TIME);
+SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
+SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
+DROP TABLE t1;
+
+#
+# ROW tests
+#
+# ROW has additional conditions when bisect is possible (see item_cmpfunc.h):
+#
+# ((is_top_level_item && not_negated) || // 3
+# (arg0_can_not_be_null && list_does_not_have_nulls) // 4
+
+# Testing all combinations of the condition components
+#
+# tli - is_top_level_item
+# nneg - not_negated
+# a0nnul - arg0_can_not_be_null
+# lnnul - list_does_not_have_nulls
+# cond3 - condition 3 is true?
+# cond4 - condition 4 is true?
+# bisect - bisect is possible (cond3 orded with cond4)
+
+# Note:
+# - using an expression in SELECT list makes top_level_item() to be false
+# - using an expression in WHERE clause makes top_leve_item() to be true
+
+--echo # Not top level, negated: cond3 is false
+
+# tli nneg a0nnul lnnul cond3 cond4 bisect
+# --- --- ------ ----- ----- ----- ------
+# 0 0 0 0 0 0 0
+# 0 0 0 1 0 0 0
+# 0 0 1 0 0 0 0
+# 0 0 1 1 0 1 1
+
+# ROW with scalar elements
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,a) NOT IN ((1,1),(2,NULL)) FROM t1;
+SELECT ROW(a,a) NOT IN ((1,1),(2,2)) FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL, b INT);
+SELECT ROW(a,a) NOT IN ((1,1),(2,NULL)) FROM t1;
+SELECT ROW(a,a) NOT IN ((1,1),(2,2)) FROM t1;
+DROP TABLE t1;
+
+# ROW with a nested ROW
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2))) FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+SELECT ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2))) FROM t1;
+DROP TABLE t1;
+
+--echo # Not top level, not negated: cond3 is false
+
+# tli nneg a0nnul lnnul cond3 cond4 bisect
+# --- --- ------ ----- ----- ----- ------
+# 0 1 0 0 0 0 0
+# 0 1 0 1 0 0 0
+# 0 1 1 0 0 0 0
+# 0 1 1 1 0 1 1
+
+# ROW with scalar elements
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,a) IN ((1,1),(2,NULL)) FROM t1;
+SELECT ROW(a,a) IN ((1,1),(2,2)) FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT ROW(a,a) IN ((1,1),(2,NULL)) FROM t1;
+SELECT ROW(a,a) IN ((1,1),(2,2)) FROM t1;
+DROP TABLE t1;
+
+# ROW with a nested ROW
+CREATE TABLE t1 (a INT);
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2))) FROM t1;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL))) FROM t1;
+SELECT ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2))) FROM t1;
+DROP TABLE t1;
+
+
+--echo # Top level, negated: cond3 is false
+
+# tli nneg a0nnul lnnul cond3 cond4 bisect
+# --- --- ------ ----- ----- ----- ------
+# 1 0 0 0 0 0 0
+# 1 0 0 1 0 0 0
+# 1 0 1 0 0 0 0
+# 1 0 1 1 0 1 1
+
+# ROW with scalar elements
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,NULL));
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,2));
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,NULL));
+SELECT 1 FROM t1 WHERE ROW(a,a) NOT IN ((1,1),(2,2));
+DROP TABLE t1;
+
+# ROW with a nested ROW
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL)));
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2)));
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,NULL)));
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) NOT IN ((1,(1,1)),(2,(2,2)));
+DROP TABLE t1;
+
+--echo # Top level, not negated: cond3 is true
+
+# tli nneg a0nnul lnnul cond3 cond4 bisect
+# --- --- ------ ----- ----- ----- ------
+# 1 1 0 0 1 0 1
+# 1 1 0 1 1 1 1
+# 1 1 1 0 1 0 1
+# 1 1 1 1 1 1 1
+
+# ROW with scalar elements
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,NULL));
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,2));
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,NULL));
+SELECT 1 FROM t1 WHERE ROW(a,a) IN ((1,1),(2,2));
+DROP TABLE t1;
+
+# ROW with a nested ROW
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)));
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)));
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL);
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)));
+SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)));
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
+--echo #
+
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
+
+PREPARE stmt FROM "SELECT
+ TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('A'),('B'),('A');
+# Compatible types
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A');
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN ('A',b);
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,a);
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b);
+# Incompatible types
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A',10);
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN ('A',b,10);
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,a,10);
+SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b,10);
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
+--echo #
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT * FROM t1 WHERE -1 IN (a,b);
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
+--echo #
+
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT
+ CASE -1
+ WHEN -9223372036854775808 THEN 'one'
+ WHEN 18446744073709551615 THEN 'two'
+ END AS c;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
+--echo #
+SELECT
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ END AS good,
+ CASE TIME'10:20:30'
+ WHEN 102030 THEN 'one'
+ WHEN TIME'10:20:31' THEN 'two'
+ WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
+ END AS was_bad_now_good;
+
+
+SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
+SET SESSION debug_dbug="-d,Item_func_in";
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index abc86476a6b..1038fc0f6d0 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -745,7 +745,7 @@ DROP TABLE t1;
CREATE TABLE t1(f1 int);
INSERT INTO t1 values (0),(0);
--disable_ps_protocol
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT POLYGON((SELECT 1 FROM (SELECT 1 IN (GROUP_CONCAT(t1.f1)) FROM t1, t1 t GROUP BY t.f1 ) d));
--enable_ps_protocol
DROP TABLE t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 8bbc9e6a040..d847f7cd5f7 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -1702,5 +1702,30 @@ insert into t1 value (1),(2);
select count(*)+sleep(0) from t1;
drop table t1;
-
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-9408 CREATE TABLE SELECT MAX(int_column) creates different columns for table vs view
+--echo #
+
+CREATE TABLE t1 (
+ id int(11) NOT NULL PRIMARY KEY,
+ country varchar(32),
+ code int(11) default NULL
+);
+INSERT INTO t1 VALUES (1,'ITALY',100),(2,'ITALY',200),(3,'FRANCE',100), (4,'ITALY',100);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+CREATE TABLE t2 AS SELECT code, COUNT(DISTINCT country), MAX(id) FROM t1 GROUP BY code ORDER BY MAX(id);
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 AS SELECT code, COUNT(DISTINCT country), MAX(id) FROM v1 GROUP BY code ORDER BY MAX(id);
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/func_hybrid_type.test b/mysql-test/t/func_hybrid_type.test
index dd8a399025b..954c7de53fa 100644
--- a/mysql-test/t/func_hybrid_type.test
+++ b/mysql-test/t/func_hybrid_type.test
@@ -155,6 +155,8 @@ CREATE TABLE t1 (a TIMESTAMP);
INSERT INTO t1 VALUES ('2010-01-01 10:20:30');
# Expect TIMESTAMP type (7) in metadata
SELECT GREATEST(a,a) FROM t1;
+# Similar to this one
+SELECT COALESCE(a,a) FROM t1;
DROP TABLE t1;
--disable_metadata
--enable_ps_protocol
@@ -459,3 +461,157 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12497 Wrong data type for LEAST(latin1_expr, utf8_expr)
+--echo #
+
+CREATE TABLE t1 AS SELECT
+ LEAST(_latin1'aaa',_utf8 0xC39F) AS c1,
+ COALESCE(_latin1'aaa',_utf8 0xC39F) AS c2;
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12504 Wrong data type for LEAST(date_expr,time_expr)
+--echo #
+
+CREATE TABLE t1 AS SELECT
+ LEAST(DATE'2001-01-01', TIME'10:20:30') AS c1,
+ CONCAT(LEAST(DATE'2001-01-01', TIME'10:20:30')) AS c2;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12505 Wrong data type for GREATEST(bit_column, int_column)
+--echo #
+
+CREATE TABLE t1 (a BIT(64),b INT);
+INSERT INTO t1 VALUES (0xFFFFFFFFFFFFFFFF,-1);
+SELECT a>b, COALESCE(a,b), GREATEST(a,b) FROM t1;
+CREATE TABLE t2 AS SELECT COALESCE(a,b),GREATEST(a,b) FROM t1;
+SELECT * FROM t2;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12601 Hybrid functions create a column of an impossible type DOUBLE(256,4)
+--echo #
+
+CREATE TABLE t1 (a DOUBLE(255,4),b DOUBLE(255,3));
+CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12617 CASE and CASE-alike hybrid functions do not preserve exact data types
+--echo #
+
+CREATE TABLE t1 (a FLOAT(10,2));
+CREATE TABLE t2 AS SELECT COALESCE(a) FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a FLOAT(10,2));
+CREATE TABLE t2 AS SELECT LEAST(a,a) FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a TINYINT(1));
+CREATE TABLE t2 AS SELECT COALESCE(a) FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2, t1;
+
+CREATE TABLE t1 (a TINYINT(1));
+CREATE TABLE t2 AS SELECT LEAST(a,a) FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2, t1;
+
+--echo #
+--echo # MDEV-12875 Wrong VIEW column data type for COALESCE(int_column)
+--echo #
+
+CREATE TABLE t1 (a INT);
+CREATE OR REPLACE VIEW v1 AS SELECT COALESCE(a) FROM t1;
+DESCRIBE v1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-10309 COALESCE(12345678900) makes a column of a wrong type and truncates the data
+--echo #
+
+CREATE TABLE t1 AS SELECT 12345678900 AS c1, COALESCE(12345678900) AS c2;
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS SELECT
+ 9 AS i1, COALESCE(9) AS c1,
+ 99 AS i2, COALESCE(99) AS c2,
+ 999 AS i3, COALESCE(999) AS c3,
+ 9999 AS i4, COALESCE(9999) AS c4,
+ 99999 AS i5, COALESCE(99999) AS c5,
+ 999999 AS i6, COALESCE(999999) AS c6,
+ 9999999 AS i7, COALESCE(9999999) AS c7,
+ 99999999 AS i8, COALESCE(99999999) AS c8,
+ 999999999 AS i9, COALESCE(999999999) AS c9,
+ 2147483647, COALESCE(2147483647),
+ 2147483648, COALESCE(2147483648),
+ 9999999999 AS i10, COALESCE(9999999999) AS c10,
+ 99999999999 AS i11, COALESCE(99999999999) AS c11,
+ 999999999999 AS i12, COALESCE(999999999999) AS c12,
+ 9999999999999 AS i13, COALESCE(9999999999999) AS c13,
+ 99999999999999 AS i14, COALESCE(99999999999999) AS c14,
+ 999999999999999 AS i15, COALESCE(999999999999999) AS c15,
+ 9999999999999999 AS i16, COALESCE(9999999999999999) AS c16,
+ 99999999999999999 AS i17, COALESCE(99999999999999999) AS c17,
+ 999999999999999999 AS i18, COALESCE(999999999999999999) AS c18,
+ 9223372036854775807, COALESCE(9223372036854775807),
+ 9223372036854775808, COALESCE(9223372036854775808),
+ 9999999999999999999 AS i19, COALESCE(9999999999999999999) AS c19,
+ 18446744073709551615, COALESCE(18446744073709551615),
+ 18446744073709551616, COALESCE(18446744073709551616),
+ 99999999999999999999 AS i20, COALESCE(99999999999999999999) AS c20,
+ 999999999999999999999 AS i21, COALESCE(999999999999999999999) AS c21,
+ 9999999999999999999999 AS i22, COALESCE(9999999999999999999999) AS c22;
+SHOW CREATE TABLE t1;
+--vertical_results
+SELECT * FROM t1;
+--horizontal_results
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-9406 CREATE TABLE..SELECT creates different columns for IFNULL() and equivalent COALESCE,CASE,IF
+--echo #
+CREATE TABLE t1 (a SMALLINT);
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 AS SELECT
+ IFNULL(a,a) AS c1,
+ COALESCE(a,a) AS c2,
+ CASE WHEN a IS NOT NULL THEN a ELSE a END AS c3,
+ IF(a IS NULL,a,a) AS c4 FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2,t1;
+
+CREATE TABLE t1 AS SELECT
+ connection_id() AS c0,
+ IFNULL(connection_id(),connection_id()) AS c1,
+ COALESCE(connection_id(), connection_id()) AS c2,
+ CASE WHEN 0 THEN connection_id() ELSE connection_id() END AS c3,
+ IF(0,connection_id(),connection_id()) AS c4;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
+
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index 6cbd5a63706..10e4a43c934 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -641,3 +641,29 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1 AND 1 IN (1,a,'3');
--echo # Not Ok to propagate equalities into the left IN argument in case of multiple comparison types
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1 AND a IN (1,2,'3');
DROP TABLE t1;
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
+--echo #
+
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
+PREPARE stmt FROM "SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+--echo #
+--echo # MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
+--echo #
+CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
+SELECT * FROM t1 WHERE -1 IN (a,b);
+PREPARE stmt FROM 'SELECT * FROM t1 WHERE -1 IN (a,b)';
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test
index 0fc8e97b284..ee7e51241d4 100644
--- a/mysql-test/t/func_json.test
+++ b/mysql-test/t/func_json.test
@@ -296,3 +296,26 @@ INSERT INTO t1 VALUES (0);
SELECT JSON_KEYS(f) FROM t1 ORDER BY 1;
DROP TABLE t1;
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+
+SELECT
+ JSON_VALID('{"id": 1, "name": "Monty"}') AS json_valid,
+ JSON_EXISTS('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2") AS json_exists,
+ JSON_CONTAINS('{"A": 0, "B": {"C": 1}, "D": 2}', '2', '$.A') AS ison_contains,
+ JSON_CONTAINS_PATH('{"A": 1, "B": [2], "C": [3, 4]}', 'one', '$.A', '$.D') AS json_contains_path;
+
+SELECT
+ JSON_LENGTH('{"a": 1, "b": {"c": 30}}') AS json_length,
+ JSON_DEPTH('[10, {"a": 20}]') AS json_depnth;
+
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index f1db36d605f..ee70102c496 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -352,10 +352,10 @@ DROP TABLE t1;
--echo # Bug#11764994 57900: CREATE TABLE .. SELECT ASSERTS SCALE >= 0 && PRECISION > 0 && SCALE <= PR
--echo #
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
CREATE TABLE t1 SELECT CEIL(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
-DROP TABLE t1;
--echo #
--echo # Bug#11765923 58937: MANY VALGRIND ERRORS AFTER GROUPING BY RESULT OF DECIMAL COLUMN FUNCTION
@@ -608,3 +608,50 @@ select 0=0, 0=-0, 0.0= -0.0, 0.0 = -(0.0), 0.0E1=-0.0E1, 0.0E1=-(0.0E1);
--echo #
select CRC32(NULL), CRC32(''), CRC32('MySQL'), CRC32('mysql'), CRC32('01234567'), CRC32('012345678');
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12000 ROUND(expr,const_expr_returning_NULL) creates DOUBLE(0,0)
+--echo #
+
+CREATE OR REPLACE TABLE t1 AS SELECT
+ ROUND(10,NULL) AS c1,
+ ROUND(10.1,NULL) AS c2,
+ ROUND(10e0,NULL) AS c3;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12857 Out-of-range errors on CREATE..SELECT 2222222222 DIV 1
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE OR REPLACE TABLE t1 AS SELECT
+ 2 DIV 1 AS d01,
+ 222222222 DIV 1 AS d09,
+ 2222222222 DIV 1 AS d10;
+SHOW CREATE TABLE t1;
+--vertical_results
+SELECT * FROM t1;
+--horizontal_results
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-12858 Out-of-range error for CREATE..SELECT unsigned_int_column+1
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE OR REPLACE TABLE t1 (a INT UNSIGNED NOT NULL);
+INSERT INTO t1 VALUES (0xFFFFFFFF);
+CREATE OR REPLACE TABLE t2 AS SELECT a+1 AS a FROM t1;
+SHOW CREATE TABLE t2;
+SELECT a, HEX(a) FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index f931352c0e2..c661819424a 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -1127,3 +1127,19 @@ DROP TABLE t1;
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+
+SELECT INET_ATON("255.255.255.255.255.255.255.255");
+
+--enable_ps_protocol
+--disable_metadata
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index e039e48a888..2f7dd638445 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -119,6 +119,7 @@ select rpad('abcd',7,'ab'),lpad('abcd',7,'ab');
select rpad('abcd',1,'ab'),lpad('abcd',1,'ab');
select rpad('STRING', 20, CONCAT('p','a','d') );
select lpad('STRING', 20, CONCAT('p','a','d') );
+select rpad('abcd',7),lpad('abcd',7);
select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD');
select least(1,2,3) | greatest(16,32,8), least(5,4)*1,greatest(-1.0,1.0)*1,least(3,2,1)*1.0,greatest(1,1.1,1.0),least("10",9),greatest("A","B","0");
@@ -373,7 +374,9 @@ select collation(right(_latin2'a',1)), coercibility(right(_latin2'a',1));
select collation(substring(_latin2'a',1,1)), coercibility(substring(_latin2'a',1,1));
select collation(concat(_latin2'a',_latin2'b')), coercibility(concat(_latin2'a',_latin2'b'));
select collation(lpad(_latin2'a',4,_latin2'b')), coercibility(lpad(_latin2'a',4,_latin2'b'));
+select collation(lpad(_latin2'a',4)), coercibility(lpad(_latin2'a',4));
select collation(rpad(_latin2'a',4,_latin2'b')), coercibility(rpad(_latin2'a',4,_latin2'b'));
+select collation(rpad(_latin2'a',4)), coercibility(rpad(_latin2'a',4));
select collation(concat_ws(_latin2'a',_latin2'b')), coercibility(concat_ws(_latin2'a',_latin2'b'));
select collation(make_set(255,_latin2'a',_latin2'b',_latin2'c')), coercibility(make_set(255,_latin2'a',_latin2'b',_latin2'c'));
select collation(export_set(255,_latin2'y',_latin2'n',_latin2' ')), coercibility(export_set(255,_latin2'y',_latin2'n',_latin2' '));
@@ -408,6 +411,8 @@ select
concat(_latin2'a',_latin2'b'),
lpad(_latin2'a',4,_latin2'b'),
rpad(_latin2'a',4,_latin2'b'),
+ lpad(_latin2'a',4),
+ rpad(_latin2'a',4),
concat_ws(_latin2'a',_latin2'b'),
make_set(255,_latin2'a',_latin2'b',_latin2'c'),
export_set(255,_latin2'y',_latin2'n',_latin2' '),
@@ -485,6 +490,8 @@ explain extended select concat('*',space(5),'*');
explain extended select reverse('abc');
explain extended select rpad('a',4,'1');
explain extended select lpad('a',4,'1');
+explain extended select rpad('a',4);
+explain extended select lpad('a',4);
explain extended select concat_ws(',','',NULL,'a');
explain extended select make_set(255,_latin2'a', _latin2'b', _latin2'c');
explain extended select elt(2,1);
@@ -1105,6 +1112,21 @@ select rpad('hello', -18446744073709551616, '1');
select rpad('hello', 18446744073709551616, '1');
select rpad('hello', -18446744073709551617, '1');
select rpad('hello', 18446744073709551617, '1');
+select rpad('hello', -1);
+select rpad('hello', -4294967295);
+select rpad('hello', 4294967295);
+select rpad('hello', -4294967296);
+select rpad('hello', 4294967296);
+select rpad('hello', -4294967297);
+select rpad('hello', 4294967297);
+select rpad('hello', -18446744073709551615);
+select rpad('hello', 18446744073709551615);
+select rpad('hello', -18446744073709551616);
+select rpad('hello', 18446744073709551616);
+select rpad('hello', -18446744073709551617);
+select rpad('hello', 18446744073709551617);
+select rpad('hello', 0, 'x');
+select rpad('hello', 0);
select lpad('hello', -1, '1');
select lpad('hello', -4294967295, '1');
@@ -1119,7 +1141,32 @@ select lpad('hello', -18446744073709551616, '1');
select lpad('hello', 18446744073709551616, '1');
select lpad('hello', -18446744073709551617, '1');
select lpad('hello', 18446744073709551617, '1');
-
+select lpad('hello', -1);
+select lpad('hello', -4294967295);
+select lpad('hello', 4294967295);
+select lpad('hello', -4294967296);
+select lpad('hello', 4294967296);
+select lpad('hello', -4294967297);
+select lpad('hello', 4294967297);
+select lpad('hello', -18446744073709551615);
+select lpad('hello', 18446744073709551615);
+select lpad('hello', -18446744073709551616);
+select lpad('hello', 18446744073709551616);
+select lpad('hello', -18446744073709551617);
+select lpad('hello', 18446744073709551617);
+select lpad('hello', 0, 'x');
+select lpad('hello', 0);
+
+--echo Check parameters count rpad / lpad
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select rpad('x');
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select rpad('x',2,'.','z');
+
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select lpad('x');
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select lpad('x',2,'.','z');
#
# BUG#17047: CHAR() and IN() can return NULL without signaling NULL
@@ -1141,6 +1188,8 @@ select substring('abc', cast(2 as unsigned int));
select repeat('a', cast(2 as unsigned int));
select rpad('abc', cast(5 as unsigned integer), 'x');
select lpad('abc', cast(5 as unsigned integer), 'x');
+select rpad('abc', cast(5 as unsigned integer));
+select lpad('abc', cast(5 as unsigned integer));
#
# Bug#15757: Wrong SUBSTRING() result when a tmp table was employed.
@@ -1403,6 +1452,8 @@ SELECT RIGHT('1', DAY(FROM_UNIXTIME(-1)));
SELECT REPEAT('1', DAY(FROM_UNIXTIME(-1)));
SELECT RPAD('hi', DAY(FROM_UNIXTIME(-1)),'?');
SELECT LPAD('hi', DAY(FROM_UNIXTIME(-1)),'?');
+SELECT RPAD('hi', DAY(FROM_UNIXTIME(-1)));
+SELECT LPAD('hi', DAY(FROM_UNIXTIME(-1)));
#
# MDEV-4289 Assertion `0' fails in make_sortkey with GROUP_CONCAT, MAKE_SET, GROUP BY
@@ -1554,6 +1605,8 @@ format(rpad('111111111.1',
# But in mysqltest --disable_prepare_warnings affects SELECT queries only
# and can't suppress prepare time warnings for DO.
#
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT
round(
concat( (
@@ -1800,7 +1853,42 @@ SELECT f1,HEX(f2) FROM t1 WHERE f1='YQ==' AND (f2= from_base64(
SELECT f1,HEX(f2) FROM t1 WHERE f1='YQ==' AND (f2= from_base64("Yq==") OR f2= from_base64("YQ=="));
DROP TABLE t1;
+--echo #
+--echo # MDEV-12685 Oracle-compatible function CHR()
+--echo #
+select chr(65);
+create database mysqltest1 CHARACTER SET = 'utf8' COLLATE = 'utf8_bin';
+use mysqltest1;
+select charset(chr(65)), length(chr(65)),char_length(chr(65));
+select charset(chr(14844588)), length(chr(14844588)),char_length(chr(14844588));
+drop database mysqltest1;
+use test;
--echo #
--echo # End of 10.1 tests
--echo #
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12592 Illegal mix of collations with the HEX function
+--echo #
+
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES (0x09),('a');
+SELECT IF(a<' ',HEX(a),a) FROM t1 ORDER BY a;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12783 sql_mode=ORACLE: Functions LENGTH() and LENGTHB()
+--echo #
+SELECT LENGTHB('a'), LENGTHB(_utf8 0xC39F), LENGTHB(123), LENGTH(null);
+EXPLAIN EXTENDED SELECT LENGTH('a'), LENGTHB('a');
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 6e0169d97ca..a3f542aaf57 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1817,3 +1817,66 @@ DROP TABLE t1,t2;
--echo #
--echo # End of 10.1 tests
--echo #
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12515 Wrong value when storing DATE_ADD() and ADDTIME() to a numeric field
+--echo #
+
+SET sql_mode='';
+
+CREATE TABLE t1 AS SELECT
+ DATE_ADD('2001-01-01',INTERVAL 1 DAY) AS c1,
+ ADDTIME('10:20:30',1) AS c2;
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t2 (c INT);
+INSERT INTO t2 SELECT DATE_ADD('2001-01-01',INTERVAL 1 DAY);
+INSERT INTO t2 VALUES ('2001-01-02');
+SELECT * FROM t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 (a INT);
+INSERT INTO t2 VALUES (ADDTIME('10:20:30',1));
+INSERT INTO t2 VALUES ('10:20:31');
+SELECT * FROM t2;
+DROP TABLE t2;
+
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-12860 Out-of-range error on CREATE..SELECT with a view using MAX and EXTRACT(MINUTE_MICROSECOND..)
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 (
+ id bigint(11) NOT NULL PRIMARY KEY,
+ dt datetime(6)
+);
+INSERT INTO t1 VALUES (1,'2001-01-01 11:22:33.123456');
+CREATE OR REPLACE VIEW v1 AS SELECT EXTRACT(MINUTE_MICROSECOND FROM dt) AS dt2 FROM t1;
+DESCRIBE v1;
+SELECT * FROM v1;
+CREATE TABLE t2 AS SELECT MAX(dt2) FROM v1;
+DESCRIBE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP VIEW v1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+--echo #
+--echo # MDEV-12866 Out-of-range error with CREATE..SELECT..TO_SECONDS(NOW())
+--echo #
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE TABLE t1 AS SELECT TO_SECONDS('9999-12-31 23:59:59');
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/t/get_diagnostics.test b/mysql-test/t/get_diagnostics.test
index 0b0d8a77087..a30bad72136 100644
--- a/mysql-test/t/get_diagnostics.test
+++ b/mysql-test/t/get_diagnostics.test
@@ -631,6 +631,7 @@ DROP PROCEDURE p1;
--echo # The same statement information item can be used multiple times.
--echo
+SHOW WARNINGS;
DELIMITER |;
CREATE PROCEDURE p1()
BEGIN
diff --git a/mysql-test/t/gis-debug.test b/mysql-test/t/gis-debug.test
index 4b36a8e20e0..588bc706370 100644
--- a/mysql-test/t/gis-debug.test
+++ b/mysql-test/t/gis-debug.test
@@ -20,3 +20,94 @@ CREATE TABLE t1 (a INT DEFAULT ST_GIS_DEBUG(1));
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # Comparison data type aggregation for pluggable data types
+--echo #
+
+SET SESSION debug_dbug="+d,Item_func_in";
+SET SESSION debug_dbug="+d,Predicant_to_list_comparator";
+
+CREATE TABLE t1 (a POINT);
+INSERT INTO t1 VALUES (POINT(1,1)),(POINT(1,2)),(POINT(1,3));
+SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30));
+SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30),'test');
+SELECT COUNT(*) FROM t1 WHERE a IN ('test','test1');
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TEXT);
+INSERT INTO t1 VALUES ('test'),('test1'),('test2');
+SELECT * FROM t1 WHERE a IN ('test',POINT(1,1));
+DROP TABLE t1;
+
+SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
+SET SESSION debug_dbug="-d,Item_func_in";
+
+
+--echo #
+--echo # MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
+--echo #
+
+# This tests is to check that operators '+' and '*' are commutative,
+# while operators '/', '-' and 'MOD' are not commutative.
+#
+# It forces substitution of type_aggregator_for_{plus|minus|mul|div|mod} to
+# type_aggregator_for_result / type_aggregator_non_commutative_test,
+# which have pairs:
+# (GEOMETRY,GEOMETRY)->GEOMETRY
+# (GEOMETRY,VARCHAR)->GEOMETRY
+# Note, they don't not have a pair:
+# (VARCHAR,GEOMETRY)->GEOMETRY
+#
+# Commutative operators should work for all these argument type combinations:
+# (GEOMETRY,GEOMETRY), (GEOMETRY,VARCHAR), (VARCHAR,GEOMETRY).
+# Non-commutative operators should work for:
+# (GEOMETRY,GEOMETRY), (GEOMETRY,VARCHAR),
+# but should fail for (VARCHAR,GEOMETRY).
+#
+# Note, LIMIT 0 is needed to avoid calling str_op(), which does DBUG_ASSERT(0).
+
+SET debug_dbug='+d,num_op';
+
+# (GEOMETRY,GEOMETRY) gives GEOMETRY for all operators
+CREATE TABLE t1 AS SELECT
+ POINT(0,0)+POINT(0,0),
+ POINT(0,0)-POINT(0,0),
+ POINT(0,0)*POINT(0,0),
+ POINT(0,0)/POINT(0,0),
+ POINT(0,0) MOD POINT(0,0) LIMIT 0;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+# (GEOMETRY,VARCHAR) gives GEOMETRY for all operators
+CREATE TABLE t1 AS SELECT
+ POINT(0,0)+'0',
+ POINT(0,0)-'0',
+ POINT(0,0)*'0',
+ POINT(0,0)/'0',
+ POINT(0,0) MOD '0' LIMIT 0;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+# (VARCHAR,GEOMETRY) gives GEOMETRY for commutative operators
+CREATE TABLE t1 AS SELECT
+ '0'+POINT(0,0),
+ '0'*POINT(0,0) LIMIT 0;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+# (VARCHAR,GEOMETRY) gives an error for non-commutative operators
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+CREATE TABLE t1 AS SELECT '0'/POINT(0,0) LIMIT 0;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0;
+
+SET debug_dbug='-d,num_op';
diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test
index 5e57569a912..1f8259bb828 100644
--- a/mysql-test/t/gis-precise.test
+++ b/mysql-test/t/gis-precise.test
@@ -134,6 +134,7 @@ geomfromtext('POLYGON((525298.67 183511.53,525296.57
183491.55))'))) st_u;
SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ASTEXT(TOUCHES(@a, GEOMFROMTEXT('point(0 0)'))) t;
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index a17d691b6f2..976398359c6 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -61,7 +61,7 @@ while ($1)
let $2=10;
while ($2)
{
- eval DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point($1 * 10 - 9, $2 * 10 - 9), Point($1 * 10, $2 * 10))));
+ eval DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point($1 * 10 - 9, $2 * 10 - 9), 0)));
SELECT count(*) FROM t2;
dec $2;
}
@@ -998,11 +998,17 @@ DROP TABLE t1;
--echo #
CREATE TABLE t1 (a GEOMETRY NOT NULL, SPATIAL KEY(a)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (Point(1,1)),(Point(2,2)),(Point(3,3));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1.0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,1e0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIME'00:00:00');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,DATE'2001-01-01');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
EXPLAIN SELECT * FROM t1 WHERE CONTAINS(a,TIMESTAMP'2001-01-01 00:00:00');
DROP TABLE t1;
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 6e4ae6d624c..538718f21ba 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -590,7 +590,7 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
-SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
+SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersects FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
@@ -669,6 +669,7 @@ INSERT INTO t1 VALUES
'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))'));
--echo # must not crash
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1);
DROP TABLE t1;
@@ -705,7 +706,7 @@ drop table t1;
# Bug#44684: valgrind reports invalid reads in
# Item_func_spatial_collection::val_str
#
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT MultiPoint(12345,'');
#SELECT MultiPoint(123451,'');
#SELECT MultiPoint(1234512,'');
@@ -732,7 +733,7 @@ SELECT MultiPoint(12345,'');
#
# Bug55531 crash with conversions of geometry types / strings
#
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
@@ -825,7 +826,7 @@ SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20)));
--echo # GEOMETRY FUNCTION ARGUMENTS
--echo #
--replace_regex /non geometric .* value/non geometric '' value/
---error ER_ILLEGAL_VALUE_FOR_TYPE
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
--echo #
@@ -1372,6 +1373,7 @@ create table t1(a geometry not null)engine=myisam;
insert into t1 values(geomfromtext("POINT(0 0)"));
insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
insert into t1 values(geomfromtext("POINT(0 9.2233720368548e18)"));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
select equals(`a`,convert(`a` using utf8)) from `t1`;
select equals(`a`,left(`a`,23)) from `t1`;
drop table t1;
@@ -1395,6 +1397,7 @@ INSERT INTO g1 VALUES (geomfromtext('point(1 2)'));
FLUSH TABLES;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM g1
FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
;
@@ -1745,5 +1748,947 @@ SELECT c FROM t1;
DROP TABLE t1;
--echo #
---echo # End of 10.2 tests
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-11478 Result data type aggregation for pluggable data types
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p2(query TEXT)
+BEGIN
+ DECLARE errcount INT DEFAULT 0;
+ DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+ BEGIN
+ SET errcount = errcount+1;
+ #SHOW WARNINGS;
+ GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
+ SELECT @p AS `ERROR: `;
+ END;
+ SELECT query AS ``;
+ EXECUTE IMMEDIATE query;
+ IF errcount = 0
+ THEN
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END IF;
+END;
+$$
+CREATE PROCEDURE p1(query TEXT)
+BEGIN
+ SELECT query AS `-------------------------------------`;
+ EXECUTE IMMEDIATE query;
+ CALL p2('CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1');
+ CALL p2('CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1');
+ CALL p2('CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1');
+ CALL p2('CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1');
+ CALL p2('CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1');
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+
+--disable_query_log
+CALL p1('CREATE TABLE t1 (a CHAR(10), b Point)');
+CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point)');
+CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point)');
+CALL p1('CREATE TABLE t1 (a TEXT, b Point)');
+CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point)');
+CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point)');
+
+CALL p1('CREATE TABLE t1 (a TINYINT, b Point)');
+CALL p1('CREATE TABLE t1 (a SMALLINT, b Point)');
+CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point)');
+CALL p1('CREATE TABLE t1 (a INT, b Point)');
+CALL p1('CREATE TABLE t1 (a BIGINT, b Point)');
+CALL p1('CREATE TABLE t1 (a FLOAT, b Point)');
+CALL p1('CREATE TABLE t1 (a DOUBLE, b Point)');
+CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point)');
+CALL p1('CREATE TABLE t1 (a BIT(8), b Point)');
+
+CALL p1('CREATE TABLE t1 (a TIME, b Point)');
+CALL p1('CREATE TABLE t1 (a DATE, b Point)');
+CALL p1('CREATE TABLE t1 (a DATETIME, b Point)');
+CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point)');
+CALL p1('CREATE TABLE t1 (a YEAR, b Point)');
+
+--echo # This creates BLOB with hybrid functions, but fails on error with UNION (MDEV-11458)
+CALL p1('CREATE TABLE t1 (a ENUM(0x61), b Point)');
+CALL p1('CREATE TABLE t1 (a SET(0x61), b Point)');
+--enable_query_log
+
+CREATE TABLE t1 AS SELECT COALESCE(NULL, Point(1,1));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT NULL UNION SELECT Point(1,1);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # MDEV-11692 Comparison data type aggregation for pluggable data types
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p2(query TEXT)
+BEGIN
+ DECLARE errcount INT DEFAULT 0;
+ DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+ BEGIN
+ SET errcount = errcount+1;
+ GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
+ SELECT @p AS `ERROR: `;
+ END;
+ SELECT query AS ``;
+ EXECUTE IMMEDIATE query;
+END;
+$$
+CREATE PROCEDURE p1(query TEXT)
+BEGIN
+ SELECT query AS `-------------------------------------`;
+ EXECUTE IMMEDIATE query;
+ CALL p2('SELECT a=b FROM t1');
+ CALL p2('SELECT b=a FROM t1');
+ CALL p2('SELECT a BETWEEN b AND c FROM t1');
+ CALL p2('SELECT a IN (b,c) FROM t1');
+ CALL p2('SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1');
+ CALL p2('SELECT a=POINT(1,1) FROM t1');
+ CALL p2('SELECT POINT(1,1)=a FROM t1');
+ CALL p2('SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1');
+ CALL p2('SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1');
+ CALL p2('SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1');
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+
+CALL p1('CREATE TABLE t1 (a CHAR(10), b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a TEXT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a ENUM("a","b"), b Point, c Point)');
+
+CALL p1('CREATE TABLE t1 (a TINYINT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a SMALLINT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a INT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a BIGINT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a FLOAT, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a DOUBLE, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a BIT(8), b Point, c Point)');
+
+CALL p1('CREATE TABLE t1 (a TIME, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a DATE, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a DATETIME, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point, c Point)');
+CALL p1('CREATE TABLE t1 (a YEAR, b Point, c Point)');
+
+CALL p1('CREATE TABLE t1 (a Point, b Point, c Point)');
+
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods in Type_handler
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p2(query TEXT)
+BEGIN
+ DECLARE errcount INT DEFAULT 0;
+ DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+ BEGIN
+ SET errcount = errcount+1;
+ #SHOW WARNINGS;
+ GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
+ SELECT @p AS `ERROR: `;
+ END;
+ SELECT query AS ``;
+ EXECUTE IMMEDIATE query;
+ IF errcount = 0
+ THEN
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END IF;
+END;
+$$
+CREATE PROCEDURE p1(query TEXT)
+BEGIN
+ SELECT query AS `-------------------------------------`;
+ EXECUTE IMMEDIATE query;
+ CALL p2('CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1');
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+
+--disable_query_log
+CALL p1('CREATE TABLE t1 (a CHAR(10), b Point)');
+CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point)');
+CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point)');
+CALL p1('CREATE TABLE t1 (a TEXT, b Point)');
+CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point)');
+CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point)');
+
+CALL p1('CREATE TABLE t1 (a TINYINT, b Point)');
+CALL p1('CREATE TABLE t1 (a SMALLINT, b Point)');
+CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point)');
+CALL p1('CREATE TABLE t1 (a INT, b Point)');
+CALL p1('CREATE TABLE t1 (a BIGINT, b Point)');
+CALL p1('CREATE TABLE t1 (a FLOAT, b Point)');
+CALL p1('CREATE TABLE t1 (a DOUBLE, b Point)');
+CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point)');
+CALL p1('CREATE TABLE t1 (a BIT(8), b Point)');
+
+CALL p1('CREATE TABLE t1 (a TIME, b Point)');
+CALL p1('CREATE TABLE t1 (a DATE, b Point)');
+CALL p1('CREATE TABLE t1 (a DATETIME, b Point)');
+CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point)');
+CALL p1('CREATE TABLE t1 (a YEAR, b Point)');
+
+--echo # This LEAST(ENUM,GEOMETRY) creates BLOB, but fails on error with UNION (see MDEV-12503)
+CALL p1('CREATE TABLE t1 (a ENUM(0x61), b Point)');
+CALL p1('CREATE TABLE t1 (a SET(0x61), b Point)');
+--enable_query_log
+
+CREATE TABLE t1 AS SELECT LEAST(NULL, Point(1,1));
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+--echo #
+--echo # MDEV-12001 Split Item_func_round::fix_length_and_dec to virtual methods in Type_handler
+--echo #
+
+CREATE TABLE t1 (a GEOMETRY);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ROUND(a) FROM t1;
+DROP TABLE t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ROUND(POINT(1,1));
+
+
+--echo #
+--echo # MDEV-12199 Split Item_func_{abs|neg|int_val}::fix_length_and_dec() into methods in Type_handler
+--echo #
+
+CREATE TABLE t1 (a GEOMETRY);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT -a FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ABS(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CEILING(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT FLOOR(a) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT -COALESCE(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ABS(COALESCE(a)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CEILING(COALESCE(a)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT FLOOR(COALESCE(a)) FROM t1;
+DROP TABLE t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT -POINT(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ABS(POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CEILING(POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT FLOOR(POINT(1,1));
+
+
+--echo #
+--echo # MDEV-12239 Add Type_handler::Item_sum_{sum|avg|variance}_fix_length_and_dec()
+--echo #
+
+CREATE TABLE t1 (a GEOMETRY);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT SUM(POINT(1,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT SUM(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT SUM(COALESCE(a)) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT AVG(POINT(1,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT AVG(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT AVG(COALESCE(a)) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT VARIANCE(POINT(1,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT VARIANCE(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT VARIANCE(COALESCE(a)) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT STDDEV(POINT(1,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT STDDEV(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT STDDEV(COALESCE(a)) FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12303 Add Type_handler::Item_xxx_fix_length_and_dec() for CAST classes
+--echo #
+
+CREATE TABLE t1 (a GEOMETRY);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS CHAR) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS TIME) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DATE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(POINT(1,1) AS DATETIME) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS SIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS UNSIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DOUBLE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS CHAR) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS TIME) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DATE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(a AS DATETIME) FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS CHAR) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS TIME) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DATE) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT CAST(COALESCE(a) AS DATETIME) FROM t1;
+
+# CAST from GEOMETRY to BINARY is OK
+SELECT LENGTH(CAST(POINT(1,1) AS BINARY)) FROM t1;
+SELECT LENGTH(CAST(a AS BINARY)) FROM t1;
+SELECT LENGTH(CAST(COALESCE(a) AS BINARY)) FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
+--echo #
+
+CREATE TABLE t1 (a GEOMETRY);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) + 1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) - 1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) * 1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) / 1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) MOD 1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 + POINT(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 - POINT(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 * POINT(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 / POINT(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 MOD POINT(1,1);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT a + 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT a - 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT a * 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT a / 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT a MOD 1 FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 + a FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 - a FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 * a FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 / a FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 MOD a FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT COALESCE(a) + 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT COALESCE(a) - 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT COALESCE(a) * 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT COALESCE(a) / 1 FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT COALESCE(a) MOD 1 FROM t1;
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 + COALESCE(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 - COALESCE(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 * COALESCE(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 / COALESCE(a) FROM t1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT 1 MOD COALESCE(a) FROM t1;
+
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12514 Split Item_temporal_func::fix_length_and_dec()
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT DATE_ADD(POINT(1,1), INTERVAL 10 DAY);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT DATE_SUB(POINT(1,1), INTERVAL 10 DAY);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) + INTERVAL 10 DAY;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT POINT(1,1) - INTERVAL 10 DAY;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT INTERVAL 10 DAY + POINT(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT INTERVAL 10 DAY + POINT(1,1);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT ADDTIME(POINT(1,1), '10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT ADDTIME('10:10:10', POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT ADDTIME(POINT(1,1), TIME'10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT ADDTIME(TIME'10:10:10', POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT ADDTIME(POINT(1,1), TIMESTAMP'2001-01-01 10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT ADDTIME(TIMESTAMP'2001-01-01 10:10:10', POINT(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT STR_TO_DATE(POINT(1,1),'%M %d,%Y');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+SELECT STR_TO_DATE('2001-01-01', POINT(1,1));
+
+--echo #
+--echo # MDEV-12665 Hybrid functions do not preserve geometry type
+--echo #
+
+CREATE TABLE t1 AS SELECT
+ Point(0,0) AS p0,
+ COALESCE(Point(0,0)) AS p1,
+ CASE WHEN 0 THEN Point(0,0) ELSE Point(1,1) END AS p2;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS SELECT LEAST(Point(0,0),Point(0,0)) AS p1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ c_geometry GEOMETRY,
+ c_point POINT,
+ c_linestring LINESTRING,
+ c_polygon POLYGON,
+ c_multipoint MULTIPOINT,
+ c_multilinestring MULTILINESTRING,
+ c_multipolygon MULTIPOLYGON,
+ c_geometrycollection GEOMETRYCOLLECTION
+);
+
+CREATE TABLE t2 AS SELECT
+ COALESCE(NULL, c_geometry),
+ COALESCE(NULL, c_point),
+ COALESCE(NULL, c_linestring),
+ COALESCE(NULL, c_polygon),
+ COALESCE(NULL, c_multipoint),
+ COALESCE(NULL, c_multilinestring),
+ COALESCE(NULL, c_multipolygon),
+ COALESCE(NULL, c_geometrycollection)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 AS SELECT
+ COALESCE(c_geometry, NULL),
+ COALESCE(c_point, NULL),
+ COALESCE(c_linestring, NULL),
+ COALESCE(c_polygon, NULL),
+ COALESCE(c_multipoint, NULL),
+ COALESCE(c_multilinestring, NULL),
+ COALESCE(c_multipolygon, NULL),
+ COALESCE(c_geometrycollection, NULL)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 AS SELECT
+ COALESCE(c_geometry, c_geometry),
+ COALESCE(c_point, c_point),
+ COALESCE(c_linestring, c_linestring),
+ COALESCE(c_polygon, c_polygon),
+ COALESCE(c_multipoint, c_multipoint),
+ COALESCE(c_multilinestring, c_multilinestring),
+ COALESCE(c_multipolygon, c_multipolygon),
+ COALESCE(c_geometrycollection, c_geometrycollection)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12560 Wrong data type for SELECT NULL UNION SELECT Point(1,1)
+--echo #
+
+CREATE TABLE t1 AS SELECT NULL AS c1 UNION SELECT POINT(1,1);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1(name TEXT)
+BEGIN
+ EXECUTE IMMEDIATE CONCAT('CREATE TABLE t1 (a ', name, ')');
+ CREATE TABLE t2 AS
+ SELECT a AS a1, a AS a2, NULL AS a3 FROM t1 UNION
+ SELECT a AS a1, NULL AS a2, a AS a3 FROM t1;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+CALL p1('geometry');
+CALL p1('point');
+CALL p1('linestring');
+CALL p1('polygon');
+CALL p1('multipoint');
+CALL p1('multilinestring');
+CALL p1('multipolygon');
+CALL p1('geometrycollection');
+DROP PROCEDURE p1;
+
+--echo #
+--echo # MDEV-12798 Item_param does not preserve exact field type in EXECUTE IMMEDIATE 'CREATE TABLE AS SELECT ?' USING POINT(1,1)
+--echo #
+EXECUTE IMMEDIATE 'CREATE TABLE t1 AS SELECT ?' USING POINT(1,1);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 AS SELECT ?';
+EXECUTE stmt USING POINT(1,1);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+--disable_ps_protocol
+SELECT
+ ST_ISSIMPLE(POINT(1,1)),
+ ST_ISRING(POINT(1,1)),
+ ST_ISCLOSED(POINT(1,1)),
+ ST_DIMENSION(POINT(1,1)),
+ ST_NUMGEOMETRIES(POINT(1,1)),
+ ST_NUMINTERIORRINGS(POINT(1,1)),
+ ST_NUMPOINTS(POINT(1,1)),
+ ST_SRID(POINT(1,1));
+--enable_ps_protocol
+--disable_metadata
+
+
+--echo #
+--echo # MDEV-12803 Improve function parameter data type control
+--echo #
+
+--echo #
+--echo # Item_geometry_func_args_geometry
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_CENTROID(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ENVELOPE(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_BOUNDARY(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_STARTPOINT(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_POINTONSURFACE(1);
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_POINTN(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_POINTN(LineString(Point(1,1)),Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_BUFFER(1, 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_BUFFER(Point(1,1), Point(1,1));
+
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_ENVELOPE(?) AS g';
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING 1;
+EXECUTE stmt USING POINT(1,1);
+SHOW CREATE TABLE t1;
+SELECT ST_ASTEXT(g) FROM t1;
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_BUFFER(?,?) AS g';
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING 1,1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+EXECUTE stmt USING POINT(1,1),0;
+SHOW CREATE TABLE t1;
+SELECT ST_GEOMETRYTYPE(g) FROM t1;
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+
+--echo #
+--echo # Functions created GEOMETRY from non-GEOMETRY
+--echo #
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT(Point(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMTEXT('test', Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(1, 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYFROMWKB(Point(1,1), Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(1,1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMFROMGEOJSON(Point(1,1), Point(1,1));
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(ROW(1,1),1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(POINT(1,1),1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(1,ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT POINT(1,POINT(1,1));
+
+
+PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT ST_GEOMFROMTEXT(?,?) AS g';
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING 1,1;
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+EXECUTE stmt USING POINT(1,1),POINT(1,1);
+EXECUTE stmt USING 'POINT(1 1)',1;
+SHOW CREATE TABLE t1;
+SELECT ST_ASTEXT(g), SRID(g) FROM t1;
+DROP TABLE t1;
+DEALLOCATE PREPARE stmt;
+
+
+
+--echo # Item_func_spatial_collection
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT GEOMETRYCOLLECTION(POINT(1,1), 1);
+
+--echo # Item_func_spatial_operation
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_UNION(POINT(1,1), 1);
+
+--echo # Item_binary_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASWKB(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASWKB(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASWKB('test');
+
+
+--echo # Item_real_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_X(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_X(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_X('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_Y(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_Y(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_Y('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_AREA(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_AREA(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_AREA('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_LENGTH(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_LENGTH(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_LENGTH('test');
+
+
+--echo # Item_real_func_geometry_args_geometry_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(ROW(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(1, 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE('test', 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(POINT(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DISTANCE(POINT(1,1), 'test');
+
+
+--echo # Item_int_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISSIMPLE(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISSIMPLE(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISSIMPLE('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISRING(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISRING(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISRING('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISCLOSED(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISCLOSED(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISCLOSED('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DIMENSION(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DIMENSION(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_DIMENSION('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMGEOMETRIES(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMGEOMETRIES(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMGEOMETRIES('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMINTERIORRINGS(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMINTERIORRINGS(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMINTERIORRINGS('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMPOINTS(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMPOINTS(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_NUMPOINTS('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_SRID(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_SRID(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_SRID('test');
+
+
+--echo # Item_bool_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISEMPTY(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISEMPTY(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ISEMPTY('test');
+
+--echo # Item_bool_func_geometry_args_geometry_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(ROW(1,1), POINT(1,1), 'T*F**FFF*');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(POINT(1,1), ROW(1,1), 'T*F**FFF*');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(1, POINT(1,1), 'T*F**FFF*');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(POINT(1,1), 1, 'T*F**FFF*');
+SELECT ST_RELATE(Point(1,1),Point(1,1),'T*F**FFF*') AS equals;
+SELECT ST_RELATE(Point(1,1),Point(1,1),NULL);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),1.0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),1e0);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIME'10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),DATE'2010-01-01');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),TIMESTAMP'2010-01-01 10:10:10');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_RELATE(Point(1,1),Point(1,1),Point(1,1));
+
+
+--echo # Item_str_ascii_func_args_geometry
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASTEXT(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASTEXT(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASTEXT('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYTYPE(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYTYPE(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_GEOMETRYTYPE('test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON('test');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(POINT(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_ASGEOJSON(POINT(1,1), 1, POINT(1,1));
+
+--echo # Item_func_spatial_rel
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(POINT(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES('test', POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT ST_TOUCHES(POINT(1,1), 'test');
+
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(ROW(1,1), POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(POINT(1,1), ROW(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(1, POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(POINT(1,1), 1);
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES('test', POINT(1,1));
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+SELECT MBRTOUCHES(POINT(1,1), 'test');
+
+--echo #
+--echo # End of 10.3 tests
--echo #
diff --git a/mysql-test/t/intersect.test b/mysql-test/t/intersect.test
new file mode 100644
index 00000000000..6028b2fa498
--- /dev/null
+++ b/mysql-test/t/intersect.test
@@ -0,0 +1,192 @@
+create table t1 (a int, b int);
+create table t2 (c int, d int);
+insert into t1 values (1,1),(2,2);
+insert into t2 values (2,2),(3,3);
+
+(select a,b from t1) intersect (select c,d from t2);
+
+drop tables t1,t2;
+
+
+create table t1 (a int, b int) engine=MyISAM;
+create table t2 (c int, d int) engine=MyISAM;
+create table t3 (e int, f int) engine=MyISAM;
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3),(4,4);
+insert into t3 values (1,1),(2,2),(5,5);
+
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+EXPLAIN (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+EXPLAIN extended (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+EXPLAIN extended select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+EXPLAIN format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+
+prepare stmt from "(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);";
+execute stmt;
+execute stmt;
+
+prepare stmt from "select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a";
+execute stmt;
+execute stmt;
+
+(select a,b from t1) intersect (select c,e from t2,t3);
+EXPLAIN (select a,b from t1) intersect (select c,e from t2,t3);
+EXPLAIN extended (select a,b from t1) intersect (select c,e from t2,t3);
+EXPLAIN extended select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a;
+EXPLAIN format=json (select a,b from t1) intersect (select c,e from t2,t3);
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json (select a,b from t1) intersect (select c,e from t2,t3);
+--replace_regex /"r_total_time_ms": [0-9e\.\-+]*,/"r_total_time_ms": "REPLACED",/
+ANALYZE format=json select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a;
+select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a;
+
+prepare stmt from "(select a,b from t1) intersect (select c,e from t2,t3);";
+execute stmt;
+execute stmt;
+
+prepare stmt from "select * from ((select a,b from t1) intersect (select c,e from t2,t3)) a";
+execute stmt;
+execute stmt;
+
+
+drop tables t1,t2,t3;
+
+
+select 1 as a from dual intersect select 1 from dual;
+(select 1 from dual) intersect (select 1 from dual);
+--error ER_WRONG_USAGE
+(select 1 from dual into @v) intersect (select 1 from dual);
+--error ER_PARSE_ERROR
+select 1 from dual ORDER BY 1 intersect select 1 from dual;
+
+select 1 as a from dual union all select 1 from dual;
+--error ER_WRONG_USAGE
+select 1 from dual intersect all select 1 from dual;
+
+
+
+create table t1 (a int, b blob, a1 int, b1 blob);
+create table t2 (c int, d blob, c1 int, d1 blob);
+insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt");
+insert into t2 values (2, "fgh", 2, "dffggtt"),(3, "ffggddd", 3, "dfgg");
+
+(select a,b,b1 from t1) intersect (select c,d,d1 from t2);
+
+drop tables t1,t2;
+
+create table t1 (a int, b blob) engine=MyISAM;
+create table t2 (c int, d blob) engine=MyISAM;
+create table t3 (e int, f blob) engine=MyISAM;
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3),(4,4);
+insert into t3 values (1,1),(2,2),(5,5);
+
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a;
+
+prepare stmt from "(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);";
+execute stmt;
+execute stmt;
+
+prepare stmt from "select * from ((select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3)) a";
+execute stmt;
+execute stmt;
+
+# make sure that blob is used
+create table t4 (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3);
+show create table t4;
+
+drop tables t1,t2,t3,t4;
+
+create table t1 (a int, b blob) engine=MyISAM;
+create table t2 (c int, d blob) engine=MyISAM;
+create table t3 (e int, f blob) engine=MyISAM;
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (1,1),(2,2),(3,3);
+
+
+--sorted_result
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+--sorted_result
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4) except (select 2,2);
+
+drop tables t1,t2,t3;
+
+create table t1 (a int, b int);
+create table t2 (c int, d int);
+create table t3 (e int, f int);
+insert into t1 values (1,1),(2,2),(3,3);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (1,1),(2,2),(3,3);
+
+--sorted_result
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+--sorted_result
+(select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3) union (select 4,4) except (select 2,2);
+
+drop tables t1,t2,t3;
+
+
+--echo #
+--echo # INTERSECT precedence
+--echo #
+create table t1 (a int, b blob) engine=MyISAM;
+create table t2 (c int, d blob) engine=MyISAM;
+create table t3 (e int, f blob) engine=MyISAM;
+insert into t1 values (5,5),(6,6);
+insert into t2 values (2,2),(3,3);
+insert into t3 values (1,1),(3,3);
+
+--sorted_result
+(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+explain extended
+(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+
+# test result of linear mix operation
+--sorted_result
+(select e,f from t3) intersect (select c,d from t2) union (select a,b from t1) union (select 4,4);
+explain extended
+(select e,f from t3) intersect (select c,d from t2) union (select a,b from t1) union (select 4,4);
+
+--sorted_result
+(/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#3 */ select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (/* select#5 */ select 4 AS `4`,4 AS `4`);
+
+--sorted_result
+prepare stmt from "(select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4)";
+execute stmt;
+execute stmt;
+
+create view v1 as (select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+
+--sorted_result
+select b,a,b+1 from v1;
+--sorted_result
+select b,a,b+1 from v1 where a > 3;
+
+create procedure p1()
+ select * from v1;
+--sorted_result
+call p1();
+--sorted_result
+call p1();
+drop procedure p1;
+
+create procedure p1()
+ (select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4);
+--sorted_result
+call p1();
+--sorted_result
+call p1();
+drop procedure p1;
+
+show create view v1;
+
+drop view v1;
+drop tables t1,t2,t3;
+
diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test
index 5c4c813ab39..4ac8f56afc5 100644
--- a/mysql-test/t/keywords.test
+++ b/mysql-test/t/keywords.test
@@ -171,7 +171,7 @@ create table option (option int not null);
drop table option;
--error 1193
set option=1;
---error 1193
+--error ER_PARSE_ERROR
set option option=1;
--echo #
@@ -220,3 +220,42 @@ DROP TABLE OTHERS;
CREATE TABLE immediate (immediate int);
DROP TABLE immediate;
+
+--echo #
+--echo # MDEV-10142 Pluggable parser
+--echo # Testing keywords that were added into lex.h for Oracle compatibility
+--echo # that are not reserved keywords in MariaDB
+--echo #
+
+CREATE TABLE clob (clob int);
+DROP TABLE clob;
+
+CREATE TABLE elsif (elsif INT);
+DROP TABLE elsif;
+
+CREATE TABLE exception (exception INT);
+DROP TABLE exception;
+
+CREATE TABLE raw (raw int);
+DROP TABLE raw;
+
+CREATE TABLE varchar2 (varchar2 int);
+DROP TABLE varchar2;
+
+CREATE TABLE decode (decode int);
+DROP TABLE decode;
+
+CREATE TABLE rowcount (rowcount int);
+DROP TABLE rowcount;
+
+CREATE TABLE isopen (isopen int);
+DROP TABLE isopen;
+
+CREATE TABLE notfound (notfound int);
+DROP TABLE notfound;
+
+CREATE TABLE raise (raise int);
+DROP TABLE raise;
+
+CREATE TABLE reuse (reuse int);
+DROP TABLE reuse;
diff --git a/mysql-test/t/lowercase_view.test b/mysql-test/t/lowercase_view.test
index 52be911cde0..4c91383db60 100644
--- a/mysql-test/t/lowercase_view.test
+++ b/mysql-test/t/lowercase_view.test
@@ -74,12 +74,6 @@ update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
-- error 1093
update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
-- error 1443
-delete from v2Aa where col1 = (select max(col1) from v1Aa);
--- error 1443
-delete from v2aA where col1 = (select max(col1) from t1Aa);
--- error 1093
-delete from v2Aa where col1 = (select max(col1) from v2aA);
--- error 1443
delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
-- error 1443
delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 09f313616f1..95c78caf034 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -2764,39 +2764,6 @@ update m1 set a = ((select max(a) from v1));
--error ER_VIEW_PREVENT_UPDATE
update m1 set a = ((select max(a) from tmp, v1));
-
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from m1);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from m2);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from t1);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from t2);
-
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from t3, m1);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from t3, m2);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from t3, t1);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from t3, t2);
-
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from tmp, m1);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from tmp, m2);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from tmp, t1);
---error ER_UPDATE_TABLE_USED
-delete from m1 where a = (select max(a) from tmp, t2);
-
---error ER_VIEW_PREVENT_UPDATE
-delete from m1 where a = (select max(a) from v1);
---error ER_VIEW_PREVENT_UPDATE
-delete from m1 where a = (select max(a) from tmp, v1);
-
drop view v1;
drop temporary table tmp;
drop table t1, t2, t3, m1, m2;
diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test
index f5ed65cf7e2..96189a9750a 100644
--- a/mysql-test/t/metadata.test
+++ b/mysql-test/t/metadata.test
@@ -14,6 +14,51 @@ drop table if exists t1,t2;
#
select 1, 1.0, -1, "hello", NULL;
+SELECT
+ 1 AS c1,
+ 11 AS c2,
+ 111 AS c3,
+ 1111 AS c4,
+ 11111 AS c5,
+ 111111 AS c6,
+ 1111111 AS c7,
+ 11111111 AS c8,
+ 111111111 AS c9,
+ 1111111111 AS c10,
+ 11111111111 AS c11,
+ 111111111111 AS c12,
+ 1111111111111 AS c13,
+ 11111111111111 AS c14,
+ 111111111111111 AS c15,
+ 1111111111111111 AS c16,
+ 11111111111111111 AS c17,
+ 111111111111111111 AS c18,
+ 1111111111111111111 AS c19,
+ 11111111111111111111 AS c20,
+ 111111111111111111111 AS c21;
+
+SELECT
+ -1 AS c1,
+ -11 AS c2,
+ -111 AS c3,
+ -1111 AS c4,
+ -11111 AS c5,
+ -111111 AS c6,
+ -1111111 AS c7,
+ -11111111 AS c8,
+ -111111111 AS c9,
+ -1111111111 AS c10,
+ -11111111111 AS c11,
+ -111111111111 AS c12,
+ -1111111111111 AS c13,
+ -11111111111111 AS c14,
+ -111111111111111 AS c15,
+ -1111111111111111 AS c16,
+ -11111111111111111 AS c17,
+ -111111111111111111 AS c18,
+ -1111111111111111111 AS c19,
+ -11111111111111111111 AS c20,
+ -111111111111111111111 AS c21;
create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, l datetime, m enum('a','b'), n set('a','b'), o char(10));
select * from t1;
@@ -207,3 +252,234 @@ drop table t1;
--enable_metadata
select cast('01:01:01' as time), cast('01:01:01' as time(2));
--disable_metadata
+
+
+--echo #
+--echo # MDEV-12854 Synchronize CREATE..SELECT data type and result set metadata data type for INT functions
+--echo #
+
+--enable_metadata
+SELECT
+ STRCMP('a','b'),
+ OCTET_LENGTH('a'),
+ CHAR_LENGTH('a'),
+ COERCIBILITY('a'),
+ ASCII('a'),
+ ORD('a'),
+ CRC32('a'),
+ UNCOMPRESSED_LENGTH(COMPRESS('a'));
+
+SELECT
+ INTERVAL(2,1,2,3),
+ REGEXP_INSTR('a','a'),
+ LOCATE('a','a'),
+ FIND_IN_SET('b','a,b,c,d'),
+ FIELD('a','a','b');
+
+SELECT
+ SIGN(1),
+ BIT_COUNT(1);
+
+
+SELECT
+ BENCHMARK(0,0),
+ SLEEP(0);
+
+SELECT
+ GET_LOCK('metadata',0),
+ IS_FREE_LOCK('metadata'),
+ RELEASE_LOCK('metadata');
+
+# Metadata the following functions is not deterministic
+#SELECT CONNECTION_ID();
+#SELECT IS_FREE_LOCK('metadata');
+#SELECT UUID_SHORT();
+
+
+SELECT
+ PERIOD_ADD(200801,2),
+ PERIOD_DIFF(200802,200703),
+ TO_DAYS('2007-10-07'),
+ DAYOFMONTH('2007-02-03'),
+ DAYOFWEEK('2007-02-03'),
+ TO_SECONDS('2013-06-13');
+
+SELECT
+ YEAR('2001-02-03 04:05:06.000007'),
+ DAY('2001-02-03 04:05:06.000007'),
+ HOUR('2001-02-03 04:05:06.000007'),
+ MINUTE('2001-02-03 04:05:06.000007'),
+ SECOND('2001-02-03 04:05:06.000007'),
+ MICROSECOND('2001-02-03 04:05:06.000007');
+
+SELECT
+ WEEK('2001-02-03 04:05:06.000007'),
+ QUARTER('2001-02-03 04:05:06.000007'),
+ YEARWEEK('2001-02-03 04:05:06.000007');
+
+--disable_metadata
+
+--enable_metadata
+SELECT BIT_LENGTH(10);
+SELECT 1|2, 1&2, 1<<2, 1>>2, ~0, 1^2;
+SELECT LAST_INSERT_ID();
+SELECT ROW_COUNT(), FOUND_ROWS();
+SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');
+--disable_metadata
+
+
+--echo #
+--echo # MDEV-12856 Wrong result set metadata for DIV
+--echo #
+
+--enable_metadata
+SELECT
+ 2 DIV 1 AS d0l,
+ 222222222 DIV 1 AS d09,
+ 2222222222 DIV 1 AS d10;
+--disable_metadata
+
+
+--echo #
+--echo # MDEV-12862 Data type of @a:=1e0 depends on the session character set
+--echo #
+--enable_metadata
+SET NAMES utf8;
+CREATE TABLE t1 AS SELECT @:=1e0;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET NAMES latin1;
+CREATE TABLE t1 AS SELECT @:=1e0;
+SELECT * FROM t1;
+DROP TABLE t1;
+--disable_metadata
+
+--echo #
+--echo # MDEV-12869 Wrong metadata for integer additive and multiplicative operators
+--echo #
+
+--enable_metadata
+SELECT
+ 1+1,
+ 11+1,
+ 111+1,
+ 1111+1,
+ 11111+1,
+ 111111+1,
+ 1111111+1,
+ 11111111+1,
+ 111111111+1 LIMIT 0;
+
+SELECT
+ 1-1,
+ 11-1,
+ 111-1,
+ 1111-1,
+ 11111-1,
+ 111111-1,
+ 1111111-1,
+ 11111111-1,
+ 111111111-1 LIMIT 0;
+
+SELECT
+ 1*1,
+ 11*1,
+ 111*1,
+ 1111*1,
+ 11111*1,
+ 111111*1,
+ 1111111*1,
+ 11111111*1,
+ 111111111*1 LIMIT 0;
+
+SELECT
+ 1 MOD 1,
+ 11 MOD 1,
+ 111 MOD 1,
+ 1111 MOD 1,
+ 11111 MOD 1,
+ 111111 MOD 1,
+ 1111111 MOD 1,
+ 11111111 MOD 1,
+ 111111111 MOD 1,
+ 1111111111 MOD 1,
+ 11111111111 MOD 1 LIMIT 0;
+
+SELECT
+ -(1),
+ -(11),
+ -(111),
+ -(1111),
+ -(11111),
+ -(111111),
+ -(1111111),
+ -(11111111),
+ -(111111111) LIMIT 0;
+
+SELECT
+ ABS(1),
+ ABS(11),
+ ABS(111),
+ ABS(1111),
+ ABS(11111),
+ ABS(111111),
+ ABS(1111111),
+ ABS(11111111),
+ ABS(111111111),
+ ABS(1111111111) LIMIT 0;
+
+SELECT
+ CEILING(1),
+ CEILING(11),
+ CEILING(111),
+ CEILING(1111),
+ CEILING(11111),
+ CEILING(111111),
+ CEILING(1111111),
+ CEILING(11111111),
+ CEILING(111111111),
+ CEILING(1111111111) LIMIT 0;
+
+SELECT
+ FLOOR(1),
+ FLOOR(11),
+ FLOOR(111),
+ FLOOR(1111),
+ FLOOR(11111),
+ FLOOR(111111),
+ FLOOR(1111111),
+ FLOOR(11111111),
+ FLOOR(111111111),
+ FLOOR(1111111111) LIMIT 0;
+
+SELECT
+ ROUND(1),
+ ROUND(11),
+ ROUND(111),
+ ROUND(1111),
+ ROUND(11111),
+ ROUND(111111),
+ ROUND(1111111),
+ ROUND(11111111),
+ ROUND(111111111),
+ ROUND(1111111111) LIMIT 0;
+
+--disable_metadata
+
+--echo #
+--echo # MDEV-12546 Wrong metadata or data type for string user variables
+--echo #
+SET @a='test';
+--enable_metadata
+SELECT @a;
+--disable_metadata
+CREATE TABLE t1 AS SELECT @a;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--enable_metadata
+SELECT @b1:=10, @b2:=@b2:=111111111111;
+--disable_metadata
+CREATE TABLE t1 AS SELECT @b1:=10, @b2:=111111111111;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 3de35a74a73..403790356ce 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -414,8 +414,14 @@ CREATE TABLE t1
c_double DOUBLE,
c_decimal103 DECIMAL(10,3),
c_varchar10 VARCHAR(10),
+ c_tinytext TINYTEXT,
c_text TEXT,
+ c_mediumtext MEDIUMTEXT,
+ c_longtext LONGTEXT,
+ c_tinyblob TINYBLOB,
c_blob BLOB,
+ c_mediumblob MEDIUMBLOB,
+ c_longblob LONGBLOB,
c_enum ENUM('one','two','tree'),
c_datetime3 DATETIME(3),
c_timestamp3 TIMESTAMP(3),
@@ -597,6 +603,27 @@ SHOW CREATE TABLE t2;
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
+ NULLIF(c_tinytext, 1),
+ NULLIF(c_tinytext, c_smallint),
+ NULLIF(c_tinytext, c_tinyint),
+ NULLIF(c_tinytext, c_int),
+ NULLIF(c_tinytext, c_bigint),
+ NULLIF(c_tinytext, c_float),
+ NULLIF(c_tinytext, c_double),
+ NULLIF(c_tinytext, c_decimal103),
+ NULLIF(c_tinytext, c_varchar10),
+ NULLIF(c_tinytext, c_text),
+ NULLIF(c_tinytext, c_blob),
+ NULLIF(c_tinytext, c_enum),
+ NULLIF(c_tinytext, c_datetime3),
+ NULLIF(c_tinytext, c_timestamp3),
+ NULLIF(c_tinytext, c_date),
+ NULLIF(c_tinytext, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 AS SELECT
NULLIF(c_text, 1),
NULLIF(c_text, c_smallint),
NULLIF(c_text, c_tinyint),
@@ -617,7 +644,70 @@ FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
-# QQ: this should probably create BLOB instead of LONGBLOB
+CREATE TABLE t2 AS SELECT
+ NULLIF(c_mediumtext, 1),
+ NULLIF(c_mediumtext, c_smallint),
+ NULLIF(c_mediumtext, c_tinyint),
+ NULLIF(c_mediumtext, c_int),
+ NULLIF(c_mediumtext, c_bigint),
+ NULLIF(c_mediumtext, c_float),
+ NULLIF(c_mediumtext, c_double),
+ NULLIF(c_mediumtext, c_decimal103),
+ NULLIF(c_mediumtext, c_varchar10),
+ NULLIF(c_mediumtext, c_text),
+ NULLIF(c_mediumtext, c_blob),
+ NULLIF(c_mediumtext, c_enum),
+ NULLIF(c_mediumtext, c_datetime3),
+ NULLIF(c_mediumtext, c_timestamp3),
+ NULLIF(c_mediumtext, c_date),
+ NULLIF(c_mediumtext, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 AS SELECT
+ NULLIF(c_longtext, 1),
+ NULLIF(c_longtext, c_smallint),
+ NULLIF(c_longtext, c_tinyint),
+ NULLIF(c_longtext, c_int),
+ NULLIF(c_longtext, c_bigint),
+ NULLIF(c_longtext, c_float),
+ NULLIF(c_longtext, c_double),
+ NULLIF(c_longtext, c_decimal103),
+ NULLIF(c_longtext, c_varchar10),
+ NULLIF(c_longtext, c_text),
+ NULLIF(c_longtext, c_blob),
+ NULLIF(c_longtext, c_enum),
+ NULLIF(c_longtext, c_datetime3),
+ NULLIF(c_longtext, c_timestamp3),
+ NULLIF(c_longtext, c_date),
+ NULLIF(c_longtext, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+
+CREATE TABLE t2 AS SELECT
+ NULLIF(c_tinyblob, 1),
+ NULLIF(c_tinyblob, c_smallint),
+ NULLIF(c_tinyblob, c_tinyint),
+ NULLIF(c_tinyblob, c_int),
+ NULLIF(c_tinyblob, c_bigint),
+ NULLIF(c_tinyblob, c_float),
+ NULLIF(c_tinyblob, c_double),
+ NULLIF(c_tinyblob, c_decimal103),
+ NULLIF(c_tinyblob, c_varchar10),
+ NULLIF(c_tinyblob, c_text),
+ NULLIF(c_tinyblob, c_blob),
+ NULLIF(c_tinyblob, c_enum),
+ NULLIF(c_tinyblob, c_datetime3),
+ NULLIF(c_tinyblob, c_timestamp3),
+ NULLIF(c_tinyblob, c_date),
+ NULLIF(c_tinyblob, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
CREATE TABLE t2 AS SELECT
NULLIF(c_blob, 1),
NULLIF(c_blob, c_smallint),
@@ -639,6 +729,49 @@ FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
+CREATE TABLE t2 AS SELECT
+ NULLIF(c_mediumblob, 1),
+ NULLIF(c_mediumblob, c_smallint),
+ NULLIF(c_mediumblob, c_tinyint),
+ NULLIF(c_mediumblob, c_int),
+ NULLIF(c_mediumblob, c_bigint),
+ NULLIF(c_mediumblob, c_float),
+ NULLIF(c_mediumblob, c_double),
+ NULLIF(c_mediumblob, c_decimal103),
+ NULLIF(c_mediumblob, c_varchar10),
+ NULLIF(c_mediumblob, c_text),
+ NULLIF(c_mediumblob, c_blob),
+ NULLIF(c_mediumblob, c_enum),
+ NULLIF(c_mediumblob, c_datetime3),
+ NULLIF(c_mediumblob, c_timestamp3),
+ NULLIF(c_mediumblob, c_date),
+ NULLIF(c_mediumblob, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE TABLE t2 AS SELECT
+ NULLIF(c_longblob, 1),
+ NULLIF(c_longblob, c_smallint),
+ NULLIF(c_longblob, c_tinyint),
+ NULLIF(c_longblob, c_int),
+ NULLIF(c_longblob, c_bigint),
+ NULLIF(c_longblob, c_float),
+ NULLIF(c_longblob, c_double),
+ NULLIF(c_longblob, c_decimal103),
+ NULLIF(c_longblob, c_varchar10),
+ NULLIF(c_longblob, c_text),
+ NULLIF(c_longblob, c_blob),
+ NULLIF(c_longblob, c_enum),
+ NULLIF(c_longblob, c_datetime3),
+ NULLIF(c_longblob, c_timestamp3),
+ NULLIF(c_longblob, c_date),
+ NULLIF(c_longblob, c_time)
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+
# QQ: this should probably create a ENUM column instead of VARCHAR(4)
CREATE TABLE t2 AS SELECT
NULLIF(c_enum, 1),
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index fec5df1a1c7..3da08581a87 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -404,3 +404,46 @@ SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
DROP TABLE t1, t2;
--echo End of 5.0 tests
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12886 Different default for INT and BIGINT column in a VIEW for a SELECT with ROLLUP
+--echo #
+
+CREATE TABLE t1 (a int(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+CREATE OR REPLACE VIEW v1 AS SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
+DESCRIBE v1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a bigint(11) NOT NULL);
+INSERT INTO t1 VALUES (1),(2);
+CREATE OR REPLACE VIEW v1 AS SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
+DESCRIBE v1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-9410 VIEW over a ROLLUP query reports too large columns
+--echo #
+
+CREATE TABLE t1 (a int(10) NOT NULL, b int(20) NOT NULL);
+INSERT INTO t1 VALUES (1,1),(2,2);
+
+CREATE VIEW v1 AS SELECT a,b FROM t1;
+DESC v1;
+DROP VIEW v1;
+
+CREATE VIEW v1 AS SELECT a, b FROM t1 GROUP BY a,b;
+DESC v1;
+DROP VIEW v1;
+
+CREATE VIEW v1 AS SELECT a, b FROM t1 GROUP BY a,b WITH ROLLUP;
+DESC v1;
+DROP VIEW v1;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test
index a29a2f14d25..98eaa7a7774 100644
--- a/mysql-test/t/parser.test
+++ b/mysql-test/t/parser.test
@@ -1337,3 +1337,15 @@ create function fs() returns serial return 1;
create table t1 ( id serial );
show create table t1;
drop table t1;
+
+--echo #
+--echo # MDEV-10343 Providing compatibility for basic SQL data types
+--echo #
+CREATE TABLE clob (clob int);
+DROP TABLE clob;
+
+CREATE TABLE raw (raw int);
+DROP TABLE raw;
+
+CREATE TABLE varchar2 (varchar2 int);
+DROP TABLE varchar2;
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index d3161c9338c..608c8812e01 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -2422,6 +2422,7 @@ ENGINE=myisam
PARTITION BY LINEAR KEY () PARTITIONS 2;
INSERT INTO t1 VALUES (1,2,'test'), (2,3,'hi'), (4,5,'bye');
+--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 1 FROM t1 WHERE b < SOME
( SELECT 1 FROM t1 WHERE a >= 1
GROUP BY b WITH ROLLUP
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index a0caf4992bf..e8d5f9fa445 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -4427,6 +4427,7 @@ DROP TABLE t1;
--echo # Bug #57203 Assertion `field_length <= 255' failed.
--echo #
+--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
diff --git a/mysql-test/t/sp-anchor-row-type-cursor.test b/mysql-test/t/sp-anchor-row-type-cursor.test
new file mode 100644
index 00000000000..fe4b55aaf1a
--- /dev/null
+++ b/mysql-test/t/sp-anchor-row-type-cursor.test
@@ -0,0 +1,1095 @@
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+--echo #
+--echo # A complete working example
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE c CURSOR FOR SELECT a,b FROM t1;
+ BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE rec ROW TYPE OF c;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
+ OPEN c;
+ read_loop: LOOP
+ FETCH c INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT rec.a ,rec.b FROM dual;
+ INSERT INTO t2 VALUES (rec.a, rec.b);
+ END LOOP;
+ CLOSE c;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # cursor ROW TYPE referring to a table in a non-existing database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM tes2.t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor ROW TYPE referring to a table in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor ROW TYPE referring to a table in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM test.t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Cursor ROW TYPE referring to a view in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM v1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # cursor ROW TYPE referring to a view in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM test.v1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Checking that all cursor ROW TYPE fields are NULL by default
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A cursor ROW TYPE variable with a ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(10,'bbb');
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A cursor ROW TYPE variable with an incompatible ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(10,'bbb','ccc');
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A cursor ROW TYPE variable with a ROW variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT ROW(10,'bbb');
+ DECLARE rec2 ROW TYPE OF cur DEFAULT rec1;
+ SELECT rec2.a, rec2.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A ROW variable using a cursor ROW TYPE variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(10,'bbb');
+ DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+ SELECT rec2.a, rec2.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning cursor ROW TYPE variables with a different column count
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ DECLARE rec2 ROW TYPE OF cur2;
+ SET rec2=rec1;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ DECLARE rec2 ROW TYPE OF cur2;
+ SET rec1=rec2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning compatible cursor ROW TYPE variables (equal number of fields)
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ DECLARE rec2 ROW TYPE OF cur2;
+ SET rec1.a= 10;
+ SET rec1.b= 'bbb';
+ SET rec2=rec1;
+ SELECT rec2.x, rec2.y;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between incompatible cursor ROW TYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ DECLARE rec2 ROW(x INT,y INT,z INT);
+ SET rec2.x= 10;
+ SET rec2.y= 20;
+ SET rec2.z= 30;
+ SET rec1= rec2;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between compatible cursor ROW TYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ DECLARE rec2 ROW(x INT,y INT);
+ SET rec2.x= 10;
+ SET rec2.y= 20;
+ SET rec1= rec2;
+ SELECT rec1.a, rec1.b;
+ SET rec1.a= 11;
+ SET rec1.b= 21;
+ SET rec2= rec1;
+ SELECT rec2.x, rec2.y;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning cursor ROW TYPE from a ROW expression
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ SET rec1= ROW(10,20);
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor ROW TYPE variable with a wrong field count
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+ BEGIN
+ DECLARE rec2 ROW TYPE OF cur2;
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ CLOSE cur1;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_WRONG_NO_OF_FETCH_ARGS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor ROW TYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE rec ROW TYPE OF cur;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN cur;
+ read_loop: LOOP
+ FETCH cur INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT rec.a, rec.b, rec.c, rec.d;
+ INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+ END LOOP;
+ CLOSE cur;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor ROW TYPE variable, ROW TYPE OF cur declared inside the LOOP
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN cur;
+ read_loop: LOOP
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ FETCH cur INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT rec.a, rec.b, rec.c, rec.d;
+ INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+ END;
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor ROW TYPE variable with different column names
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+ BEGIN
+ DECLARE rec2 ROW TYPE OF cur2;
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.x, rec2.y;
+ CLOSE cur1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a cursor ROW TYPE variable, with truncation
+--echo #
+
+SET sql_mode='';
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ DECLARE cur2 CURSOR FOR SELECT * FROM t2;
+ BEGIN
+ DECLARE rec2 ROW TYPE OF cur2;
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.a, rec2.b;
+ CLOSE cur1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # cursor ROW TYPE variables are not allowed in LIMIT
+--echo #
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1 DEFAULT (1,2);
+ SELECT * FROM t1 LIMIT rec1.a;
+ END;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # cursor ROW TYPE variable fields as OUT parameters
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a INT,OUT b VARCHAR(10))
+BEGIN
+ SET a=10;
+ SET b='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ CALL p1(rec1.a, rec1.b);
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire cursor ROW TYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur DEFAULT ROW(10,'bb');
+ CALL p1(rec1);
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire cursor ROW TYPE variable as an OUT parameter
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a ROW(a INT, b VARCHAR(10)))
+BEGIN
+ SET a= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur;
+ CALL p1(rec1);
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Assigning a cursor ROW TYPE field to an OUT parameter
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1 (INOUT res INTEGER)
+BEGIN
+ DECLARE a INT DEFAULT 10;
+ DECLARE cur1 CURSOR FOR SELECT a FROM DUAL;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SET res=rec1.a;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1(@res);
+SELECT @res;
+SET @res=NULL;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing Item_splocal_row_field_by_name::print
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur1 DEFAULT ROW(10,'bb');
+ EXPLAIN EXTENDED SELECT rec.a, rec.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Run time error in the cursor statement
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT
+ 10 AS a,
+ CONCAT(_latin1'a' COLLATE latin1_bin,
+ _latin1'a' COLLATE latin1_swedish_ci) AS b;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SELECT a,b;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_CANT_AGGREGATE_2COLLATIONS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+
+--echo #
+--echo # Non-existing field
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur1;
+ SELECT rec.c;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+ALTER TABLE t1 ADD c INT;
+#
+# The below ALTER is needed as a workaround to call sp_cache_invalidate()
+# Please remove it after fixing MDEV-12166
+#
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that field names are case insensitive
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur DEFAULT ROW(10,'bb');
+ SELECT rec.A, rec.B;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that cursor ROW TYPE uses temporary tables vs shadowed real tables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur DEFAULT ROW(10,'bb');
+ SELECT rec.A, rec.B;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TEMPORARY TABLE t1;
+#
+# The below ALTER is needed as a workaround to call sp_cache_invalidate()
+# Please remove it after fixing MDEV-12166
+#
+ALTER PROCEDURE p1 COMMENT 'test';
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that the structure of cursor ROW TYPE variables is determined at the DECLARE CURSOR instantiation time
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ DROP TABLE t1;
+ CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+ BEGIN
+ DECLARE rec ROW TYPE OF cur; -- This has a column "c"
+ SET rec.c=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur; -- This does not have a column "c"
+ DROP TABLE t1;
+ CREATE TABLE t1 (a INT, b VARCHAR(32), c INT);
+ SET rec.c=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Duplicate field nams in a cursor referenced by cursor ROW TYPE
+--echo #
+
+CREATE TABLE t1 (a INT);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT * FROM t1, t2;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ SELECT rec.a;
+ SET rec.a=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_DUP_FIELDNAME
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Tricky field names a cursor referenced by cursor ROW TYPE
+--echo #
+
+SET NAMES utf8;
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('a');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur CURSOR FOR SELECT a, CONCAT(a,'a'), CONCAT(a,'ö') FROM t1;
+ BEGIN
+ DECLARE rec ROW TYPE OF cur;
+ OPEN cur;
+ FETCH cur INTO rec;
+ CLOSE cur;
+ SELECT rec.a, rec.`CONCAT(a,'a')`, rec.`CONCAT(a,'ö')`;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SET NAMES latin1;
+
+
+--echo #
+--echo # Using definitions recursively (cursor ROW TYPE variables in another cursor SELECT)
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'b1'),(20,'b2'),(30,'b3');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT a,b FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1 DEFAULT ROW(0,'b0');
+ DECLARE cur2 CURSOR FOR SELECT rec1.a AS a, rec1.b AS b FROM t1;
+ BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE rec2 ROW TYPE OF cur2;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN cur2;
+ read_loop: LOOP
+ FETCH cur2 INTO rec2;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT rec2.a, rec2.b;
+ END LOOP;
+ CLOSE cur2;
+ END;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing queries with auto-generated Items.
+--echo # An instance of Item_func_conv_charset is created during the below SELECT query.
+--echo # We check here that during an implicit cursor OPEN
+--echo # done in sp_instr_cursor_copy_struct::exec_core()
+--echo # all temporary Items are created on a proper memory root and are safely destroyed.
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1, b VARCHAR(10) CHARACTER SET utf8);
+INSERT INTO t1 VALUES (0xFF, 'a');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT CONCAT(a,b) AS c FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ OPEN cur1;
+ FETCH cur1 INTO rec1;
+ CLOSE cur1;
+ SELECT HEX(rec1.c);
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # SELECT INTO + cursor ROW TYPE variable with a wrong column count
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT 10, 'b0', 'c0';
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # SELECT INTO + multiple cursor ROW TYPE variables
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ SELECT * FROM t1 INTO rec1, rec1;
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # SELECT INTO + cursor ROW TYPE working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+
+--echo #
+--echo # MDEV-12916 Wrong column data type for an INT field of a cursor-anchored ROW variable
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT DEFAULT 10;
+ DECLARE cur1 CURSOR FOR SELECT a;
+ BEGIN
+ DECLARE rec1 ROW TYPE OF cur1;
+ CREATE TABLE t1 AS SELECT rec1.a;
+ SHOW CREATE TABLE t1;
+ DROP TABLE t1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
diff --git a/mysql-test/t/sp-anchor-row-type-table.test b/mysql-test/t/sp-anchor-row-type-table.test
new file mode 100644
index 00000000000..97e0a1d5805
--- /dev/null
+++ b/mysql-test/t/sp-anchor-row-type-table.test
@@ -0,0 +1,761 @@
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+--echo #
+--echo # Referring to a table in a non-existing database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF test2.t1;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a table in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF t1;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a table in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF test.t1;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a view in the current database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF v1;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referring to a view in an explicitly specified database
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF test.v1;
+ CREATE TABLE t2 AS SELECT rec.a, rec.b, rec.c, rec.d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10));
+CREATE VIEW v1 AS SELECT * FROM t1;
+CALL p1();
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Checking that all table ROW TYPE fields are NULL by default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ SELECT rec1.a, rec1.b, rec1.c, rec1.d;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A table ROW TYPE variable with a ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bbb');
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A table ROW TYPE variable with an incompatible ROW expression as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bbb','ccc');
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A table ROW TYPE variable with a ROW variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT ROW(10,'bbb');
+ DECLARE rec2 ROW TYPE OF t1 DEFAULT rec1;
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A ROW variable using a table ROW TYPE variable as a default
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bbb');
+ DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning table ROW TYPE variables with a different column count
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE);
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ DECLARE rec2 ROW TYPE OF t2;
+ SET rec2=rec1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ DECLARE rec2 ROW TYPE OF t2;
+ SET rec1=rec2;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning compatible table ROW TYPE variables (equal number of fields)
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ DECLARE rec2 ROW TYPE OF t2;
+ SET rec1.a= 10;
+ SET rec1.b= 'bbb';
+ SET rec2=rec1;
+ SELECT rec2.x, rec2.y;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between incompatible table ROW TYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ DECLARE rec2 ROW(x INT,y INT,z INT);
+ SET rec2.x= 10;
+ SET rec2.y= 20;
+ SET rec2.z= 30;
+ SET rec1= rec2;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning between compatible table ROW TYPE and explicit ROW variables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ DECLARE rec2 ROW(x INT,y INT);
+ SET rec2.x= 10;
+ SET rec2.y= 20;
+ SET rec1= rec2;
+ SELECT rec1.a, rec1.b;
+ SET rec1.a= 11;
+ SET rec1.b= 21;
+ SET rec2= rec1;
+ SELECT rec2.x, rec2.y;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning table ROW TYPE from a ROW expression
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ SET rec1= ROW(10,20);
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a table ROW TYPE variable with a wrong field count
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec2 ROW TYPE OF t2;
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ CLOSE cur1;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_WRONG_NO_OF_FETCH_ARGS
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a table ROW TYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,2));
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (10,'bb1',111.111e2, 12.31);
+INSERT INTO t1 VALUES (20,'bb2',222.222e2, 12.32);
+INSERT INTO t1 VALUES (30,'bb3',333.333e2, 12.33);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE rec ROW TYPE OF t1;
+ DECLARE cur CURSOR FOR SELECT * FROM t1;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN cur;
+ read_loop: LOOP
+ FETCH cur INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT rec.a, rec.b, rec.c, rec.d;
+ INSERT INTO t2 VALUES (rec.a, rec.b, rec.c, rec.d);
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Fetching a cursor into a table ROW TYPE variable with different column names
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (x INT, y VARCHAR(10));
+INSERT INTO t1 VALUES (10,'bbb');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec2 ROW TYPE OF t2;
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.x, rec2.y;
+ CLOSE cur1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Fetching a cursor into a table ROW TYPE variable, with truncation
+--echo #
+
+SET sql_mode='';
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b INT);
+INSERT INTO t1 VALUES (10,'11x');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec2 ROW TYPE OF t2;
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ OPEN cur1;
+ FETCH cur1 INTO rec2;
+ SELECT rec2.a, rec2.b;
+ CLOSE cur1;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t2;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+
+--echo #
+--echo # table ROW TYPE variables are not allowed in LIMIT
+--echo #
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2);
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1 DEFAULT (1,2);
+ SELECT * FROM t1 LIMIT rec1.a;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # table ROW TYPE variable fields as OUT parameters
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a INT,OUT b VARCHAR(10))
+BEGIN
+ SET a=10;
+ SET b='bb';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ CALL p1(rec1.a, rec1.b);
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire table ROW TYPE variable
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT, b VARCHAR(10)))
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+ CALL p1(rec1);
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Passing the entire table ROW TYPE variable as an OUT parameter
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a ROW(a INT, b VARCHAR(10)))
+BEGIN
+ SET a= ROW(10,'bb');
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ CALL p1(rec1);
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Assigning a table ROW TYPE field to an OUT parameter
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1 (INOUT res INTEGER)
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1 DEFAULT ROW(10,'b0');
+ SET res=rec1.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1(@res);
+SELECT @res;
+SET @res=NULL;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing Item_splocal_row_field_by_name::print
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+ EXPLAIN EXTENDED SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Non-existing field
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF t1;
+ SELECT rec.c;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+ALTER TABLE t1 ADD c INT;
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that field names are case insensitive
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+ SELECT rec.A, rec.B;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Testing that table ROW TYPE uses temporary tables vs shadowed real tables
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TEMPORARY TABLE t1 (x INT, y VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW TYPE OF t1 DEFAULT ROW(10,'bb');
+ SELECT rec.A, rec.B;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TEMPORARY TABLE t1;
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Testing that the structure of table ROW TYPE variables is determined at the very beginning and is not changed after ALTER
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ ALTER TABLE t1 ADD c INT;
+ BEGIN
+ DECLARE rec ROW TYPE OF t1; -- this will not have column "c"
+ SET rec.c=10;
+ END;
+END;
+$$
+DELIMITER ;$$
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # SELECT INTO + table ROW TYPE variable with a wrong column count
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ SELECT 10,'a','b' FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # SELECT INTO + multiple table ROW TYPE variables
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ SELECT 10,'a' FROM t1 INTO rec1, rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # SELECT INTO + table ROW TYPE working example
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW TYPE OF t1;
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+
+--echo #
+--echo # MDEV-12347 Valgrind reports invalid read errors in Item_field_row::element_index_by_name
+--echo #
+
+# An additional test for MDEV-12347, to make sure that
+# Column_definition::interval creates a permanent copy of TYPELIB on
+# the memory root when processing %ROWTYPE for a table with ENUM/SET column,
+# rather than reuses the TYPELIB from table->field[i], which is freed in the
+# end of sp_rcontext::resolve_table_rowtype_ref().
+
+CREATE TABLE t1 (a INT, b ENUM('b0','b1','b12','b3'));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ BEGIN
+ DECLARE rec ROW TYPE OF t1;
+ SET rec.b='b0';
+ SELECT rec.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+CREATE TABLE t1 (a INT, b SET('b0','b1','b12','b3'));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ BEGIN
+ DECLARE rec ROW TYPE OF t1;
+ SET rec.b='b0';
+ SELECT rec.b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/t/sp-anchor-type.test b/mysql-test/t/sp-anchor-type.test
new file mode 100644
index 00000000000..f57342eb67c
--- /dev/null
+++ b/mysql-test/t/sp-anchor-type.test
@@ -0,0 +1,677 @@
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+--echo #
+--echo # Missing table
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Missing column
+--echo #
+
+CREATE TABLE t1 (b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # One TYPE OF variable
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a;
+ SET a= 123;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # Two TYPE OF variables, with a truncation warning on assignment
+--echo #
+
+SET sql_mode='';
+CREATE TABLE t1 (a TINYINT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a;
+ DECLARE b TYPE OF t1.b;
+ SET a= 200;
+ SET b= 200;
+ SELECT a, b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # TYPE OF variables for fields with various attributes
+--echo #
+
+CREATE TABLE t1 (
+ id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ a TINYINT NOT NULL,
+ b INT NOT NULL,
+ ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ UNIQUE(a)
+);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE id TYPE OF t1.id;
+ DECLARE a TYPE OF t1.a;
+ DECLARE b TYPE OF t1.b;
+ DECLARE ts TYPE OF t1.ts;
+ SELECT id, a, b, ts;
+ CREATE TABLE t2 AS SELECT id, a, b, ts;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # TYPE OF + virtual columns
+--echo #
+
+CREATE TABLE t1 (
+ a INT NOT NULL,
+ b VARCHAR(32),
+ c INT AS (a + 10) VIRTUAL,
+ d VARCHAR(5) AS (left(b,5)) PERSISTENT
+);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE c TYPE OF t1.c;
+ DECLARE d TYPE OF t1.d;
+ SELECT c, d;
+ CREATE TABLE t2 AS SELECT c, d;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # TYPE OF + the ZEROFILL attribute
+--echo #
+
+CREATE TABLE t1 (
+ dz DECIMAL(10,3) ZEROFILL
+);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE dzr TYPE OF t1.dz DEFAULT 10;
+ DECLARE dzt DECIMAL(10,3) ZEROFILL DEFAULT 10;
+ SELECT dzr, dzt;
+ CREATE TABLE t2 AS SELECT dzr,dzt;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Temporary tables shadow real tables for TYPE OF purposes
+--echo #
+CREATE TABLE t1 (a VARCHAR(10));
+INSERT INTO t1 VALUES ('t1');
+CREATE TEMPORARY TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+SELECT * FROM t1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a DEFAULT 11;
+ CREATE TABLE t2 AS SELECT a;
+END;
+$$
+DELIMITER ;$$
+--echo #
+--echo # Should use INT(11) as TYPE OF, as in the temporary table
+--echo #
+CALL p1();
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+SELECT * FROM t1;
+DROP TEMPORARY TABLE t1;
+SELECT * FROM t1;
+--echo #
+--echo # Should use VARCHAR(10) as TYPE OF, as in the real table
+--echo #
+CALL p1();
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # "TYPE OF t1.a" searches for "t1" in the current database
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a DEFAULT 11;
+ CREATE TABLE test.t2 AS SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # This interprets "TYPE OF t1.a" as VARCHAR(10), as in test.t1.a
+--echo #
+
+USE test;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+DROP TABLE test.t2;
+
+--echo #
+--echo # This interprets "TYPE OF t1.a" as INT, as in test1.t1.a
+--echo #
+
+USE test1;
+CALL test.p1();
+SHOW CREATE TABLE test.t2;
+DROP TABLE test.t2;
+
+--echo #
+--echo # Error if there is no an active database
+--echo #
+
+DROP DATABASE test1;
+--error ER_NO_DB_ERROR
+CALL test.p1();
+
+USE test;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # A reference to a table in a non-existing database
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF test1.t1.a;
+ CREATE TABLE t1 AS SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_NO_SUCH_TABLE
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # A reference to a table in a different database
+--echo #
+CREATE TABLE t1(a INT);
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (a VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF t1.a;
+ DECLARE b TYPE OF test1.t1.a;
+ CREATE TABLE t2 AS SELECT a,b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+SHOW CREATE TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t2;
+DROP DATABASE test1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Using a table before it appears in a TYPE OF declaration + multiple TYPE OF declarations
+--echo #
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 (a,b) VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ INSERT INTO t1 (a,b) VALUES (11, 'b11');
+ SELECT * FROM t1;
+ BEGIN
+ DECLARE va TYPE OF t1.a DEFAULT 30;
+ DECLARE vb TYPE OF t1.b DEFAULT 'b30';
+ INSERT INTO t1 (a,b) VALUES (12,'b12');
+ SELECT * FROM t1;
+ INSERT INTO t1 (a,b) VALUES (va, vb);
+ SELECT * FROM t1;
+ END;
+ BEGIN
+ DECLARE va TYPE OF t1.a DEFAULT 40;
+ DECLARE vb TYPE OF t1.b DEFAULT 'b40';
+ INSERT INTO t1 (a,b) VALUES (va,vb);
+ SELECT * FROM t1;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # TYPE OF variables + TABLE vs VIEW
+--echo #
+
+CREATE TABLE t1 (
+ bit6 BIT(6),
+ bit7 BIT(7),
+ bit8 BIT(8),
+ i1 TINYINT,
+ i2 SMALLINT,
+ i3 MEDIUMINT,
+ i4 INT,
+ i8 BIGINT,
+ ff FLOAT,
+ fd DOUBLE,
+ cc CHAR(10),
+ cv VARCHAR(10),
+ cvu VARCHAR(10) CHARACTER SET utf8,
+ t1 TINYTEXT,
+ t2 TEXT,
+ t3 MEDIUMTEXT,
+ t4 LONGTEXT,
+ enum1 ENUM('a','b','c'),
+ set1 SET('a','b','c'),
+ blob1 TINYBLOB,
+ blob2 BLOB,
+ blob3 MEDIUMBLOB,
+ blob4 LONGBLOB,
+ yy YEAR,
+ dd DATE,
+ tm0 TIME,
+ tm3 TIME(3),
+ tm6 TIME(6),
+ dt0 DATETIME,
+ dt3 DATETIME(3),
+ dt6 DATETIME(6),
+ ts0 TIMESTAMP,
+ ts3 TIMESTAMP(3),
+ ts6 TIMESTAMP(6),
+ dc100 DECIMAL(10,0),
+ dc103 DECIMAL(10,3),
+ dc209 DECIMAL(20,9)
+);
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1(command enum('create','select'))
+BEGIN
+ DECLARE bit6 TYPE OF t1.bit6 DEFAULT 0x30;
+ DECLARE bit7 TYPE OF t1.bit7 DEFAULT 0x41;
+ DECLARE bit8 TYPE OF t1.bit8 DEFAULT 0x7E;
+ DECLARE i1 TYPE OF t1.i1 DEFAULT 11;
+ DECLARE i2 TYPE OF t1.i2 DEFAULT 12;
+ DECLARE i3 TYPE OF t1.i3 DEFAULT 13;
+ DECLARE i4 TYPE OF t1.i4 DEFAULT 14;
+ DECLARE i8 TYPE OF t1.i8 DEFAULT 18;
+ DECLARE ff TYPE OF t1.ff DEFAULT 21;
+ DECLARE fd TYPE OF t1.fd DEFAULT 22;
+ DECLARE cc TYPE OF t1.cc DEFAULT 'char';
+ DECLARE cv TYPE OF t1.cv DEFAULT 'varchar';
+ DECLARE cvu TYPE OF t1.cvu DEFAULT 'varcharu8';
+ DECLARE t1 TYPE OF t1.t1 DEFAULT 'text1';
+ DECLARE t2 TYPE OF t1.t2 DEFAULT 'text2';
+ DECLARE t3 TYPE OF t1.t3 DEFAULT 'text3';
+ DECLARE t4 TYPE OF t1.t4 DEFAULT 'text4';
+ DECLARE enum1 TYPE OF t1.enum1 DEFAULT 'b';
+ DECLARE set1 TYPE OF t1.set1 DEFAULT 'a,c';
+ DECLARE blob1 TYPE OF t1.blob1 DEFAULT 'blob1';
+ DECLARE blob2 TYPE OF t1.blob2 DEFAULT 'blob2';
+ DECLARE blob3 TYPE OF t1.blob3 DEFAULT 'blob3';
+ DECLARE blob4 TYPE OF t1.blob4 DEFAULT 'blob4';
+ DECLARE yy TYPE OF t1.yy DEFAULT 2001;
+ DECLARE dd TYPE OF t1.dd DEFAULT '2001-01-01';
+ DECLARE tm0 TYPE OF t1.tm0 DEFAULT '00:00:01';
+ DECLARE tm3 TYPE OF t1.tm3 DEFAULT '00:00:03.333';
+ DECLARE tm6 TYPE OF t1.tm6 DEFAULT '00:00:06.666666';
+ DECLARE dt0 TYPE OF t1.dt0 DEFAULT '2001-01-01 00:00:01';
+ DECLARE dt3 TYPE OF t1.dt3 DEFAULT '2001-01-03 00:00:01.333';
+ DECLARE dt6 TYPE OF t1.dt6 DEFAULT '2001-01-06 00:00:01.666666';
+ DECLARE ts0 TYPE OF t1.ts0 DEFAULT '2002-01-01 00:00:01';
+ DECLARE ts3 TYPE OF t1.ts3 DEFAULT '2002-01-03 00:00:01.333';
+ DECLARE ts6 TYPE OF t1.ts6 DEFAULT '2002-01-06 00:00:01.666666';
+ DECLARE dc100 TYPE OF t1.dc100 DEFAULT 10;
+ DECLARE dc103 TYPE OF t1.dc103 DEFAULT 10.123;
+ DECLARE dc209 TYPE OF t1.dc209 DEFAULT 10.123456789;
+ CASE
+ WHEN command='create' THEN
+ CREATE TABLE t2 AS SELECT
+ bit6, bit7, bit8,
+ i1,i2,i3,i4,i8,
+ ff,fd, dc100, dc103, dc209,
+ cc,cv,cvu,
+ t1,t2,t3,t4,
+ enum1, set1,
+ blob1, blob2, blob3, blob4,
+ dd, yy,
+ tm0, tm3, tm6,
+ dt0, dt3, dt6,
+ ts0, ts3, ts6;
+ WHEN command='select' THEN
+ SELECT
+ bit6, bit7, bit8,
+ i1,i2,i3,i4,i8,
+ ff,fd, dc100, dc103, dc209,
+ cc,cv,cvu,
+ t1,t2,t3,t4,
+ enum1, set1,
+ blob1, blob2, blob3, blob4,
+ dd, yy,
+ tm0, tm3, tm6,
+ dt0, dt3, dt6,
+ ts0, ts3, ts6;
+ END CASE;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # TABLE
+--echo #
+CALL p1('create');
+SHOW CREATE TABLE t2;
+--vertical_results
+SELECT * FROM t2;
+--horizontal_results
+DROP TABLE t2;
+
+--disable_ps_protocol
+--enable_metadata
+--vertical_results
+CALL p1('select');
+--horizontal_results
+--disable_metadata
+--enable_ps_protocol
+
+--echo #
+--echo # VIEW
+--echo #
+ALTER TABLE t1 RENAME t0;
+CREATE VIEW t1 AS SELECT * FROM t0;
+
+CALL p1('create');
+SHOW CREATE TABLE t2;
+--vertical_results
+SELECT * FROM t2;
+--horizontal_results
+DROP TABLE t2;
+
+--disable_ps_protocol
+--enable_metadata
+--vertical_results
+CALL p1('select');
+--horizontal_results
+--disable_metadata
+--enable_ps_protocol
+
+DROP VIEW t1;
+DROP TABLE t0;
+
+DROP PROCEDURE p1;
+
+--echo #
+--echo # VIEW with subqueries
+--echo #
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,1),(20,2),(30,3),(40,4);
+SELECT AVG(a) FROM t1;
+CREATE VIEW v1 AS SELECT a,1 as b FROM t1 WHERE a>(SELECT AVG(a) FROM t1) AND b>(SELECT 1);
+SELECT * FROM v1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF v1.a DEFAULT 10;
+ DECLARE b TYPE OF v1.b DEFAULT 1;
+ SELECT a,b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DELIMITER $$;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ DECLARE a TYPE OF v1.a DEFAULT 10;
+ DECLARE b TYPE OF v1.b DEFAULT 1;
+ RETURN a+b;
+END;
+$$
+DELIMITER ;$$
+SELECT f1();
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # TYPE OF variables + INFORMATION_SCHEMA
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE tables_table_name TYPE OF INFORMATION_SCHEMA.TABLES.TABLE_NAME;
+ DECLARE tables_table_rows TYPE OF INFORMATION_SCHEMA.TABLES.TABLE_ROWS;
+ DECLARE processlist_info TYPE OF INFORMATION_SCHEMA.PROCESSLIST.INFO;
+ DECLARE processlist_info_binary TYPE OF INFORMATION_SCHEMA.PROCESSLIST.INFO_BINARY;
+ CREATE TABLE t1 AS SELECT
+ tables_table_name,
+ tables_table_rows,
+ processlist_info,
+ processlist_info_binary;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # TYPE OF + Table structure change
+--echo # Data type for both a0 and a1 is chosen in the very beginning
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a0 TYPE OF t1.a;
+ ALTER TABLE t1 MODIFY a VARCHAR(10); -- This does not affect a1
+ BEGIN
+ DECLARE a1 TYPE OF t1.a;
+ CREATE TABLE t2 AS SELECT a0, a1;
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+ END;
+END
+$$
+DELIMITER ;$$
+CREATE TABLE t1 (a INT);
+CALL p1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # TYPE OF in parameters
+--echo #
+CREATE TABLE t1 (a VARCHAR(10));
+CREATE DATABASE test1;
+CREATE TABLE test1.t1 (b SMALLINT);
+DELIMITER $$;
+CREATE PROCEDURE p1(a TYPE OF t1.a, b TYPE OF test1.t1.b)
+BEGIN
+ CREATE TABLE t2 AS SELECT a, b;
+END;
+$$
+DELIMITER ;$$
+CALL p1('test', 123);
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE test1.t1;
+DROP DATABASE test1;
+DROP TABLE t1;
+
+--echo #
+--echo # TYPE OF in a stored function variables and arguments
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1 (prm TYPE OF t1.a) RETURNS INT
+BEGIN
+ DECLARE a TYPE OF t1.a DEFAULT prm;
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+SELECT f1(20);
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # TYPE OF in function RETURN clause is not supported yet
+--echo #
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE FUNCTION f1() RETURN TYPE OF t1.a
+BEGIN
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Using TYPE OF variables as FETCH targets
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
+INSERT INTO t1 VALUES (1,'b1','2001-01-01 10:20:30.123');
+INSERT INTO t1 VALUES (2,'b2','2001-01-02 10:20:30.123');
+CREATE TABLE t2 LIKE t1;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a TYPE OF t1.a;
+ DECLARE v_b TYPE OF t1.b;
+ DECLARE v_c TYPE OF t1.c;
+ DECLARE c CURSOR FOR SELECT a,b,c FROM t1;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c;
+ read_loop: LOOP
+ FETCH c INTO v_a, v_b, v_c;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ INSERT INTO t2 (a,b,c) VALUES (v_a, v_b, v_c);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Using TYPE OF variables as SELECT INTO targets
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
+INSERT INTO t1 VALUES (1,'b1','2001-01-01 10:20:30.123');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE v_a TYPE OF t1.a;
+ DECLARE v_b TYPE OF t1.b;
+ DECLARE v_c TYPE OF t1.c;
+ SELECT * FROM t1 INTO v_a, v_b, v_c;
+ SELECT v_a, v_b, v_c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test
index 4671aee11e1..3239dfeaeec 100644
--- a/mysql-test/t/sp-bugs.test
+++ b/mysql-test/t/sp-bugs.test
@@ -307,3 +307,17 @@ start transaction;
call sp();
drop procedure sp;
+--echo #
+--echo # MDEV-11146 SP variables of the SET data type erroneously allow values with comma
+--echo #
+
+DELIMITER $$;
+--error ER_ILLEGAL_VALUE_FOR_TYPE
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a SET('a','b','c','a,b');
+ SET a='a,b';
+ SELECT a, a+0;
+END;
+$$
+DELIMITER ;$$
diff --git a/mysql-test/t/sp-cursor.test b/mysql-test/t/sp-cursor.test
new file mode 100644
index 00000000000..394dc56556a
--- /dev/null
+++ b/mysql-test/t/sp-cursor.test
@@ -0,0 +1,476 @@
+
+--echo #
+--echo # MDEV-12457 Cursors with parameters
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,'old'),(2,'old'),(3,'old'),(4,'old'),(5,'old');
+DELIMITER $$;
+CREATE PROCEDURE p1(min INT,max INT)
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE va INT;
+ DECLARE cur CURSOR(pmin INT, pmax INT) FOR SELECT a FROM t1 WHERE a BETWEEN pmin AND pmax;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN cur(min,max);
+ read_loop: LOOP
+ FETCH cur INTO va;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ INSERT INTO t1 VALUES (va,'new');
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1(2,4);
+SELECT * FROM t1 ORDER BY b DESC,a;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # OPEN with a wrong number of parameters
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+--error ER_WRONG_PARAMCOUNT_TO_CURSOR
+CREATE PROCEDURE p1(a_a INT,a_b VARCHAR(32))
+BEGIN
+ DECLARE v_a INT;
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR (p_a INT, p_b VARCHAR(32)) FOR SELECT * FROM t1 WHERE a=p_a;
+ OPEN c(a_a);
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # Cursor parameters are not visible outside of the cursor
+--echo #
+
+DELIMITER $$;
+--error ER_UNKNOWN_SYSTEM_VARIABLE
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+ DECLARE v_a INT;
+ DECLARE c CURSOR (p_a INT) FOR SELECT a FROM t1 WHERE a=p_a;
+ OPEN c(a_a);
+ SET p_a=10;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_UNKNOWN_SYSTEM_VARIABLE
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+ DECLARE v_a INT;
+ DECLARE c CURSOR (p_a INT) FOR SELECT a FROM t1 WHERE a=p_a;
+ SET p_a= 10;
+ OPEN c(a_a);
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Cursor parameter shadowing a local variable
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT)
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a INT DEFAULT NULL;
+ DECLARE p_a INT DEFAULT NULL;
+ DECLARE c CURSOR (p_a VARCHAR(32)) FOR SELECT p_a FROM t1;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c(a);
+ read_loop: LOOP
+ FETCH c INTO v_a;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT v_a;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1);
+CALL p1(NULL);
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Parameters in SELECT list
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR(32))
+BEGIN
+ DECLARE v_a INT;
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR (p_a INT, p_b VARCHAR(32)) FOR SELECT p_a,p_b FROM DUAL;
+ OPEN c(a_a + 0,a_b);
+ FETCH c INTO v_a, v_b;
+ SELECT v_a, v_b;
+ CLOSE c;
+ OPEN c(a_a + 1,a_b);
+ FETCH c INTO v_a, v_b;
+ SELECT v_a, v_b;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1,'b1');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Parameters in SELECT list + UNION
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR(32))
+BEGIN
+ DECLARE v_a INT;
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR(p_a INT, p_b VARCHAR(32)) FOR
+ SELECT p_a,p_b FROM DUAL
+ UNION ALL
+ SELECT p_a+1,CONCAT(p_b,'b') FROM DUAL;
+ OPEN c(a_a,a_b);
+ FETCH c INTO v_a, v_b;
+ SELECT v_a, v_b;
+ FETCH c INTO v_a, v_b;
+ SELECT v_a, v_b;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1,'b1');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Parameters in SELECT list + type conversion + warnings
+--echo #
+
+SET sql_mode='';
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a VARCHAR(32))
+BEGIN
+ DECLARE v_a INT;
+ DECLARE c CURSOR (p_a INT) FOR SELECT p_a FROM DUAL;
+ OPEN c(a_a);
+ FETCH c INTO v_a;
+ SELECT v_a;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('1b');
+CALL p1('b1');
+DROP PROCEDURE p1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # One parameter in SELECT list + subselect
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a VARCHAR(32))
+BEGIN
+ DECLARE v_a VARCHAR(10);
+ DECLARE c CURSOR (p_a VARCHAR(32)) FOR
+ SELECT p_a FROM DUAL UNION SELECT REVERSE(p_a) FROM DUAL;
+ OPEN c((SELECT a_a));
+ FETCH c INTO v_a;
+ SELECT v_a;
+ FETCH c INTO v_a;
+ SELECT v_a;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('ab');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Two parameters in SELECT list + subselect
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE v_a VARCHAR(32);
+ DECLARE v_b VARCHAR(32);
+ DECLARE c CURSOR (p_a VARCHAR(32), p_b VARCHAR(32)) FOR
+ SELECT p_a, p_b FROM DUAL
+ UNION
+ SELECT p_b, p_a FROM DUAL;
+ OPEN c((SELECT 'aaa'),(SELECT 'bbb'));
+ FETCH c INTO v_a, v_b;
+ SELECT v_a, v_b;
+ FETCH c INTO v_a, v_b;
+ SELECT v_a, v_b;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Two parameters in SELECT list + two parameters in WHERE + subselects
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a VARCHAR(32), a_b VARCHAR(32))
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a VARCHAR(32);
+ DECLARE v_b VARCHAR(32);
+ DECLARE c CURSOR (value_a VARCHAR(32), value_b VARCHAR(32),
+ pattern_a VARCHAR(32), pattern_b VARCHAR(32)) FOR
+ SELECT value_a, value_b FROM DUAL WHERE value_a LIKE pattern_a
+ UNION
+ SELECT value_b, value_a FROM DUAL WHERE value_b LIKE pattern_b;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c((SELECT 'aaa'),(SELECT 'bbb'),(SELECT a_a),(SELECT a_b));
+ read_loop: LOOP
+ FETCH c INTO v_a, v_b;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT v_a, v_b;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('%','%');
+CALL p1('aaa','xxx');
+CALL p1('xxx','bbb');
+CALL p1('xxx','xxx');
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Parameters in SELECT list + stored function
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1 (a VARCHAR(32)) RETURNS VARCHAR(32)
+BEGIN
+ RETURN CONCAT(a,'y');
+END;
+$$
+CREATE PROCEDURE p1(a_a VARCHAR(32))
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a VARCHAR(10);
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR (p_sel_a VARCHAR(32), p_cmp_a VARCHAR(32)) FOR
+ SELECT p_sel_a, p_cmp_a FROM DUAL;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c(f1(a_a), f1(a_a));
+ read_loop: LOOP
+ FETCH c INTO v_a, v_b;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT v_a, v_b;
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1('x');
+# A complex expression
+CALL p1(f1(COALESCE(NULL, f1('x'))));
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # One parameter in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a INT;
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR (p_a INT) FOR SELECT a,b FROM t1 WHERE a=p_a;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c(a_a);
+ read_loop: LOOP
+ FETCH c INTO v_a, v_b;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ INSERT INTO t2 VALUES (v_a,v_b);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1);
+SELECT * FROM t2;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Two parameters in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE TABLE t2 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'11');
+INSERT INTO t1 VALUES (1,'12');
+INSERT INTO t1 VALUES (2,'21');
+INSERT INTO t1 VALUES (2,'22');
+INSERT INTO t1 VALUES (3,'31');
+INSERT INTO t1 VALUES (3,'32');
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT, a_b VARCHAR(32))
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a INT;
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR (p_a INT, p_b VARCHAR(32)) FOR SELECT a,b FROM t1 WHERE a=p_a AND b=p_b;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c(a_a, a_b);
+ read_loop: LOOP
+ FETCH c INTO v_a, v_b;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ INSERT INTO t2 VALUES (v_a,v_b);
+ END LOOP;
+ CLOSE c;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1,'11');
+SELECT * FROM t2;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Parameters in WHERE and HAVING clauses
+--echo #
+CREATE TABLE t1 (name VARCHAR(10), value INT);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('but',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bin',1);
+INSERT INTO t1 VALUES ('bot',1);
+DELIMITER $$;
+CREATE PROCEDURE p1 (arg_name_limit VARCHAR(32), arg_total_limit INT)
+BEGIN
+ DECLARE i INT DEFAULT 0;
+ DECLARE v_name VARCHAR(10);
+ DECLARE v_total INT;
+-- +0 is needed to work around the bug MDEV-11081
+ DECLARE c CURSOR(p_v INT) FOR
+ SELECT name, SUM(value + p_v) + 0 AS total FROM t1
+ WHERE name LIKE arg_name_limit
+ GROUP BY name HAVING total>=arg_total_limit;
+ WHILE i < 2 DO
+ BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ OPEN c(i);
+ read_loop: LOOP
+ FETCH c INTO v_name, v_total;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT v_name, v_total;
+ END LOOP;
+ CLOSE c;
+ SET i= i + 1;
+ END;
+ END WHILE;
+END;
+$$
+DELIMITER ;$$
+CALL p1('%', 2);
+CALL p1('b_t', 0);
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # One parameter in LIMIT clause
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+INSERT INTO t1 VALUES (1,'b1');
+INSERT INTO t1 VALUES (2,'b2');
+INSERT INTO t1 VALUES (3,'b3');
+INSERT INTO t1 VALUES (4,'b4');
+INSERT INTO t1 VALUES (5,'b5');
+INSERT INTO t1 VALUES (6,'b6');
+DELIMITER $$;
+CREATE PROCEDURE p1(a_a INT)
+BEGIN
+ DECLARE done INT DEFAULT 0;
+ DECLARE v_a INT;
+ DECLARE v_b VARCHAR(10);
+ DECLARE c CURSOR (p_a INT) FOR SELECT a,b FROM t1 ORDER BY a LIMIT p_a;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
+ CREATE TABLE t2 (a INT, b VARCHAR(10));
+ OPEN c(a_a);
+ read_loop: LOOP
+ FETCH c INTO v_a, v_b;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ INSERT INTO t2 VALUES (v_a,v_b);
+ END LOOP;
+ CLOSE c;
+ SELECT * FROM t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1(1);
+CALL p1(3);
+CALL p1(6);
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+
+--echo #
+--echo # End of MDEV-12457 Cursors with parameters
+--echo #
diff --git a/mysql-test/t/sp-row-vs-var.inc b/mysql-test/t/sp-row-vs-var.inc
new file mode 100644
index 00000000000..54d323f7341
--- /dev/null
+++ b/mysql-test/t/sp-row-vs-var.inc
@@ -0,0 +1,6 @@
+--let $query= CREATE PROCEDURE p1() BEGIN DECLARE var $type; DECLARE rec ROW(var $type); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END
+--eval $query
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/t/sp-row.test b/mysql-test/t/sp-row.test
new file mode 100644
index 00000000000..6ed8b4495f4
--- /dev/null
+++ b/mysql-test/t/sp-row.test
@@ -0,0 +1,1473 @@
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+
+--echo #
+--echo # ROW of ROWs is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a ROW(a INT));
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Returning the entire ROW parameter from a function
+--echo #
+# TODO: this should probably return an error at compile time
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURNS INT
+BEGIN
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20));
+DROP FUNCTION f1;
+
+
+
+--echo #
+--echo # ROW as an SP parameter
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURNS INT
+BEGIN
+ RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+SELECT f1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20,30));
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+CALL p1(10);
+--error ER_OPERAND_COLUMNS
+CALL p1(ROW(10,20,30));
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP OUT parameter
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a ROW(a INT,b INT))
+BEGIN
+ SET a.a=10;
+ SET a.b=20;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+ CALL p1(a);
+ SELECT a.a,a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP return value is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE FUNCTION p1() RETURNS ROW(a INT)
+BEGIN
+ RETURN NULL;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Diplicate row field
+--echo #
+DELIMITER $$;
+--error ER_DUP_FIELDNAME
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT, a DOUBLE);
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Bad scalar default value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT, b DOUBLE) DEFAULT 1;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Bad ROW default value with a wrong number of fields
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT, b DOUBLE) DEFAULT ROW(1,2,3);
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Scalar variable vs table alias cause no ambiguity
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT;
+ -- a.x is a table column here (not a row variable field)
+ SELECT a.x FROM a;
+ SELECT a.x FROM t1 a;
+END;
+$$
+DELIMITER ;$$
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW variable in select list
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT);
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW variable in functions
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT);
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT);
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing the entire ROW to a scalar value
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT a=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT 1=a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Passing the entire ROW to a stored function
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+ RETURN a;
+END;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+#DELIMITER $$;
+#CREATE FUNCTION f1(a INT) RETURNS INT
+#BEGIN
+# RETURN a;
+#END;
+#CREATE PROCEDURE p1()
+#BEGIN
+# DECLARE a ROW (a INT);
+# SELECT f1(a);
+#END;
+#$$
+#DELIMITER ;$$
+##--error ER_OPERAND_COLUMNS
+#CALL p1();
+#DROP PROCEDURE p1;
+#DROP FUNCTION f1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 1 column
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 2 columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW value to a ROW variable with different number of columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec=ROW(1,2,3);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Returning the entire ROW from a function is not supported yet
+--echo # This syntax would be needed: SELECT f1().x FROM DUAL;
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+ DECLARE rec ROW(a INT);
+ RETURN rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Using the entire ROW in SELECT..CREATE
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW in LIMIT
+--echo #
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= '10';
+ SELECT * FROM t1 LIMIT rec;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Setting ROW fields using a SET command
+--echo #
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+ DECLARE a INT;
+ SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+ SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from a ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec=ROW(1,2);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from another ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT,b INT);
+ DECLARE rec2 ROW(a INT,b INT);
+ SET rec1=ROW(1,2);
+ SET rec2=rec1;
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to a ROW() function
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec.a= 1;
+ SET rec.b= 2;
+ SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+ SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+ SELECT rec=(NULL,0), rec=ROW(NULL,0);
+ SELECT rec=(NULL,2), rec=ROW(NULL,2);
+ SELECT rec<>(0,0), rec<>ROW(0,0);
+ SELECT rec<>(1,2), rec<>ROW(1,2);
+ SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+ SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+ SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+ SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+ SELECT rec IN ((0,NULL),(1,2));
+ SELECT rec NOT IN ((0,NULL),(1,1));
+ SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to another ROW variable
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec1,rec2,rec3 ROW(a INT,b INT);
+ SET rec1.a= 1;
+ SET rec1.b= 2;
+ SET rec2.a= 11;
+ SET rec2.b= 12;
+ SET rec3.a= 11;
+ SET rec3.b= 12;
+ SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referencing a non-existing row variable
+--echo #
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1()
+BEGIN
+ SET a.b=1;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # Referencing a non-existing row field
+--echo #
+DELIMITER $$;
+--error ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT,b INT);
+ SELECT a.c FROM t1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW and scalar variables with the same name shadowing each other
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT);
+ SET a.a=100;
+ SELECT a.a;
+ BEGIN
+ DECLARE a INT DEFAULT 200;
+ SELECT a;
+ BEGIN
+ DECLARE a ROW(a INT);
+ SET a.a=300;
+ SELECT a.a;
+ END;
+ SELECT a;
+ END;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW with good default values
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT,b INT) DEFAULT (10,20);
+ DECLARE b ROW(a INT,b INT) DEFAULT (11,21);
+ DECLARE c ROW(a INT,b INT) DEFAULT a;
+ SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT) DEFAULT ROW(10,20);
+ SELECT * FROM t1 WHERE rec=ROW(a,b);
+ SELECT * FROM t1 WHERE ROW(a,b)=rec;
+ SELECT * FROM t1 WHERE rec=ROW(10,20);
+ SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= 10;
+ SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in HAVING clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= 10;
+ SELECT * FROM t1 HAVING a=rec.a;
+ SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in LIMIT clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+--error ER_SP_UNDECLARED_VAR
+SELECT 1 FROM t1 LIMIT t1.a;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= 10;
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a VARCHAR(10));
+ SET rec.a= '10';
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW fields in select list
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE t1 ROW(a INT);
+ SET t1.a= 10;
+ SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+ SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as insert values
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10));
+ SET rec.a= 10;
+ SET rec.b= 'test';
+ INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as SP out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+ SET a= 10;
+ SET b= 'test';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10));
+ CALL p1(rec.a, rec.b);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as dynamic SQL out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+ SET a= 20;
+ SET b= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(30));
+ EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as SELECT..INTO targets
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10));
+ SELECT 10,'test' INTO rec.a,rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Implicit default NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+ SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT (NULL,NULL);
+ DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (10,20);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (NULL,20);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (10,NULL);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (NULL,NULL);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing multiple ROW variable declarations
+--echo # This makes sure that fill_field_definitions() is called only once
+--echo # per a ROW field, so create length is not converted to internal length
+--echo # multiple times.
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+ CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # INT
+--echo #
+
+--let type=INT
+--source sp-row-vs-var.inc
+
+--let type=INT(1)
+--source sp-row-vs-var.inc
+
+--let type=INT(2)
+--source sp-row-vs-var.inc
+
+--let type=INT(3)
+--source sp-row-vs-var.inc
+
+--let type=INT(4)
+--source sp-row-vs-var.inc
+
+--let type=INT(5)
+--source sp-row-vs-var.inc
+
+--let type=INT(6)
+--source sp-row-vs-var.inc
+
+--let type=INT(7)
+--source sp-row-vs-var.inc
+
+--let type=INT(8)
+--source sp-row-vs-var.inc
+
+--let type=INT(9)
+--source sp-row-vs-var.inc
+
+--let type=INT(10)
+--source sp-row-vs-var.inc
+
+--let type=INT(11)
+--source sp-row-vs-var.inc
+
+--let type=INT(12)
+--source sp-row-vs-var.inc
+
+--let type=INT(13)
+--source sp-row-vs-var.inc
+
+--let type=INT(14)
+--source sp-row-vs-var.inc
+
+--let type=INT(20)
+--source sp-row-vs-var.inc
+
+--let type=INT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # TINYINT
+--echo #
+
+--let type=TINYINT
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(1)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(2)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(3)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(4)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(5)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(6)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(7)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(8)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(9)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(10)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(11)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(12)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(13)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(14)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(20)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # SMALLINT
+--echo #
+
+--let type=SMALLINT
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(1)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(2)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(3)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(4)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(5)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(6)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(7)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(8)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(9)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(10)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(11)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(12)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(13)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(14)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(20)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # MEDIUMINT
+--echo #
+
+--let type=MEDIUMINT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(1)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(2)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(3)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(4)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(5)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(6)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(7)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(8)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(9)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(10)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(11)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(12)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(13)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(14)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(20)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # BIGINT
+--echo #
+
+--let type=BIGINT
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(1)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(2)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(3)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(4)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(5)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(6)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(7)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(8)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(9)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(10)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(11)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(12)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(13)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(14)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(20)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # DOUBLE
+--echo #
+
+--let type=DOUBLE
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,1)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,2)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,3)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,4)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,5)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,6)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,7)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,8)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,9)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,10)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,11)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,12)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,13)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,14)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,20)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # VARCHAR
+--echo #
+
+--let type=CHAR
+--source sp-row-vs-var.inc
+
+--let type=BINARY
+--source sp-row-vs-var.inc
+
+--let type=CHAR(1)
+--source sp-row-vs-var.inc
+
+--let type=CHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=NCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=BINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARBINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # TIME
+--echo #
+
+--let type=TIME
+--source sp-row-vs-var.inc
+
+--let type=TIME(1)
+--source sp-row-vs-var.inc
+
+--let type=TIME(2)
+--source sp-row-vs-var.inc
+
+--let type=TIME(3)
+--source sp-row-vs-var.inc
+
+--let type=TIME(4)
+--source sp-row-vs-var.inc
+
+--let type=TIME(5)
+--source sp-row-vs-var.inc
+
+--let type=TIME(6)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # DATETIME
+--echo #
+
+--let type=DATETIME
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(1)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(2)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(3)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(4)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(5)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(6)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # LOB
+--echo #
+
+--let type=TEXT
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT
+--source sp-row-vs-var.inc
+
+--let type=TEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+--echo #
+--echo # MDEV-12291 Allow ROW variables as SELECT INTO targets
+--echo #
+
+
+--echo # ROW variable with a wrong column count
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(32), c DOUBLE);
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # Multiple ROW variables
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(32));
+ SELECT * FROM t1 INTO rec1, rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo # ROW variables working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(32));
+ SELECT * FROM t1 INTO rec1;
+ SELECT rec1.a, rec1.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # MDEV-13273 Confusion between table alias and ROW type variable
+--echo #
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT;
+ DECLARE b INT;
+ -- a.c1 is a table column
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 0;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (c1 INT, c2 INT) DEFAULT ROW(101,102);
+ DECLARE b INT;
+ -- a.c1 is a ROW variable field
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 102;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW TYPE OF t1 DEFAULT ROW (10,20);
+ DECLARE b INT;
+ -- a.c1 is a ROW variable field
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 20;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c1 INT, c2 INT);
+INSERT INTO t1 VALUES (0,0);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE cur1 CURSOR FOR SELECT * FROM t1;
+ BEGIN
+ DECLARE a ROW TYPE OF cur1 DEFAULT ROW (10,20);
+ DECLARE b INT;
+ -- a.c1 is a ROW variable field
+ SELECT a.c1 INTO b
+ FROM t1 a
+ WHERE a.c2 = 20;
+ SELECT b;
+ END;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/t/sp-security-anchor-type.test b/mysql-test/t/sp-security-anchor-type.test
new file mode 100644
index 00000000000..e61d5e38052
--- /dev/null
+++ b/mysql-test/t/sp-security-anchor-type.test
@@ -0,0 +1,328 @@
+--source include/not_embedded.inc
+
+--echo #
+--echo # MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+
+--echo #
+--echo # Initiation:
+--echo # - creating database db1
+--echo # - creating user user1 with access rights to db1
+--echo #
+
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (a INT, b VARCHAR(10));
+
+CREATE USER user1;
+
+GRANT ALL PRIVILEGES ON test.* TO user1;
+
+connect (conn1,localhost,user1,,test);
+
+SELECT database();
+SELECT user();
+
+--echo #
+--echo # Making sure that user1 does not have privileges to db1.t1
+--echo #
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW CREATE TABLE db1.t1;
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW FIELDS IN db1.t1;
+
+
+--echo #
+--echo # Trigger: using TYPE OF with a table we don't have access to
+--echo #
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+DELIMITER $$;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+ DECLARE b TYPE OF db1.t1.b DEFAULT 20;
+ SET NEW.b = 10;
+END
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Stored procedure: Using TYPE OF for with a table that we don't have access to
+--echo # DEFINER user1, SQL SECURITY DEFAULT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+#DELIMITER $$;
+#CREATE PROCEDURE p1()
+#BEGIN
+# DECLARE a ROW TYPE OF db1.t1;
+# SELECT a.a;
+#END;
+#$$
+#DELIMITER ;$$
+#--error ER_TABLEACCESS_DENIED_ERROR
+#CALL p1;
+#DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Stored procedure: Using TYPE OF for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY INVOKER
+--echo #
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY INVOKER
+BEGIN
+ DECLARE a ROW TYPE OF db1.t1;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+--error ER_TABLEACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Stored procedure: Using TYPE OF for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY DEFINER
+--echo #
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+CALL p1;
+DROP PROCEDURE p1;
+
+connection default;
+DELIMITER $$;
+CREATE PROCEDURE p1()
+SQL SECURITY DEFINER
+BEGIN
+ DECLARE a ROW TYPE OF db1.t1;
+ SET a.a= 10;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Stored function: Using TYPE OF for with a table that we don't have access to
+--echo # DEFINER user1, SQL SECURITY DEFAULT
+--echo #
+
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 0;
+ RETURN OCTET_LENGTH(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT f1();
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Stored function: Using TYPE OF for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY INVOKER
+--echo #
+
+connection default;
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURNS INT
+SQL SECURITY INVOKER
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 0;
+ RETURN OCTET_LENGTH(a);
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+--error ER_TABLEACCESS_DENIED_ERROR
+SELECT f1();
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Stored function: Using TYPE OF for with a table that we don't have access to
+--echo # DEFINER root, SQL SECURITY DEFINER
+--echo #
+
+connection default;
+CREATE TABLE t1 (a INT);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURNS INT
+SQL SECURITY DEFINER
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 0;
+ RETURN OCTET_LENGTH(a);
+END;
+$$
+DELIMITER ;$$
+connection conn1;
+SELECT f1();
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+
+connection default;
+GRANT SELECT (a) ON db1.t1 TO user1;
+connection conn1;
+
+--echo #
+--echo # Making sure that user1 has access to db1.t1.a, but not to db1.t1.b
+--echo #
+
+--error ER_TABLEACCESS_DENIED_ERROR
+SHOW CREATE TABLE db1.t1;
+SHOW FIELDS IN db1.t1;
+
+--echo #
+--echo # Trigger: Per-column privileges
+--echo #
+CREATE TABLE test.t1 (a INT, b INT);
+INSERT INTO test.t1 (a,b) VALUES (10,20);
+SELECT * FROM t1;
+# TYPE OF reference using a column we have access to
+DELIMITER $$;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 20;
+ BEGIN
+ SET NEW.b := 10;
+ END;
+END
+$$
+DELIMITER ;$$
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+# TYPE OF reference using a column that we don't have access to
+DELIMITER $$;
+CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
+BEGIN
+ DECLARE b TYPE OF db1.t1.b DEFAULT 20;
+ BEGIN
+ SET NEW.b = 10;
+ END;
+END
+$$
+DELIMITER ;$$
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 (a) VALUES (10);
+SELECT * FROM t1;
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+
+
+--echo #
+--echo # Stored procedure: Per-column privileges
+--echo # DEFINER user1, SQL SECURITY DEFAULT
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a TYPE OF db1.t1.a DEFAULT 10;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE b TYPE OF db1.t1.b DEFAULT 10;
+ SELECT b;
+END;
+$$
+DELIMITER ;$$
+--error ER_COLUMNACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE b ROW TYPE OF db1.t1;
+ SET b.b=10;
+ SELECT b.b;
+END;
+$$
+DELIMITER ;$$
+--error ER_COLUMNACCESS_DENIED_ERROR
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Clean up
+--echo #
+disconnect conn1;
+connection default;
+
+DROP USER user1;
+DROP DATABASE db1;
+
+--echo #
+--echo # End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test
index 2e7257cbcea..57d5563e609 100644
--- a/mysql-test/t/sp-vars.test
+++ b/mysql-test/t/sp-vars.test
@@ -1487,3 +1487,52 @@ DELIMITER ;|
CALL vctest();
DROP PROCEDURE vctest;
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12876 Wrong data type for CREATE..SELECT sp_var
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE i8 TINYINT;
+ DECLARE i16 SMALLINT;
+ DECLARE i32 INT;
+ DECLARE i64 BIGINT;
+ DECLARE f FLOAT;
+ DECLARE d DOUBLE;
+ DECLARE b8 BIT(8);
+ DECLARE y YEAR;
+ DECLARE t1 TINYTEXT;
+ DECLARE t2 TEXT;
+ DECLARE t3 MEDIUMTEXT;
+ DECLARE t4 LONGTEXT;
+ CREATE TABLE t1 AS SELECT i8, i16, i32, i64, f, d, b8, y, t1, t2, t3, t4;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DESCRIBE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # MDEV-12917 Wrong data type for CREATE..SELECT year_sp_variable
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a YEAR;
+ CREATE OR REPLACE TABLE t1 AS SELECT a;
+ SHOW CREATE TABLE t1;
+ DROP TABLE t1;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 3ca210d9904..7eedc67acd9 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -8227,7 +8227,7 @@ drop procedure if exists p;
set @old_mode= @@sql_mode;
set @@sql_mode= cast(pow(2,32)-1 as unsigned integer);
select @@sql_mode into @full_mode;
-create procedure p() begin end;
+create procedure p() as begin end;
call p();
set @@sql_mode= @old_mode;
# Rename SQL modes that differ in name between the server and the table definition.
@@ -9588,3 +9588,117 @@ DELIMITER ;|
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12007 Allow ROW variables as a cursor FETCH target
+--echo #
+
+
+--echo # The cursor and the ROW variable in FETCH must have the same number of fields
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE rec ROW(aa INT, bb VARCHAR(32), cc INT);
+ DECLARE cur CURSOR FOR SELECT 10 AS a,'b10' AS b;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+ OPEN cur;
+read_loop:
+ LOOP
+ FETCH cur INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+--error ER_SP_WRONG_NO_OF_FETCH_ARGS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo # Multiple ROW variables in FETCH
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE rec1 ROW(aa INT);
+ DECLARE rec2 ROW(aa INT);
+ DECLARE cur CURSOR FOR SELECT 10 AS a, 20 AS b;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+ OPEN cur;
+read_loop:
+ LOOP
+ FETCH cur INTO rec1, rec2;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo # A complete working example
+CREATE TABLE t1 (a INT, b VARCHAR(32));
+INSERT INTO t1 VALUES (10,'b10');
+INSERT INTO t1 VALUES (20,'b20');
+INSERT INTO t1 VALUES (30,'b30');
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE rec ROW(aa INT, bb VARCHAR(32));
+ DECLARE cur CURSOR FOR SELECT a,b FROM t1;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+ OPEN cur;
+read_loop:
+ LOOP
+ FETCH cur INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT CONCAT('rec=(',rec.aa,',',rec.bb,')') AS c;
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+
+--echo # A ROW variable with a single field
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE rec ROW(aa INT);
+ DECLARE cur CURSOR FOR SELECT 10 AS a UNION SELECT 20;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+ OPEN cur;
+read_loop:
+ LOOP
+ FETCH cur INTO rec;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ SELECT CONCAT('rec=(',rec.aa,')') AS c;
+ END LOOP;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 2029e5a8f44..4d4a3f2d933 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -340,12 +340,16 @@ insert into t1 values (0, 10),(1, 11),(2, 12);
insert into t2 values (1, 21),(2, 12),(3, 23);
select * from t1;
select * from t1 where b = (select b from t2 where t1.a = t2.a);
--- error ER_UPDATE_TABLE_USED
+# Works since MDEV-12137
+# previously : ER_UPDATE_TABLE_USED
+--enable_info
delete from t1 where b in (select b from t1);
+--disable_info
+insert into t1 values (0, 10),(1, 11),(2, 12);
-- error ER_SUBQUERY_NO_1_ROW
delete from t1 where b = (select b from t2);
delete from t1 where b = (select b from t2 where t1.a = t2.a);
-select * from t1;
+select * from t1 order by b;
drop table t1, t2;
#multi-delete with subselects
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 5c65e3dd13b..aeab884670d 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2677,7 +2677,6 @@ select trigger_name, action_order, created from information_schema.triggers
drop table t1;
set time_zone= @@global.time_zone;
---echo #
--echo # MDEV-12992: Increasing memory consumption
--echo with each invocation of trigger
--echo #
@@ -2700,3 +2699,27 @@ while ($n)
--enable_query_log
DROP TABLE t1,t2;
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, total INT);
+DELIMITER $$;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+ DECLARE va TYPE OF t1.a DEFAULT NEW.a;
+ DECLARE vb TYPE OF t1.b DEFAULT NEW.b;
+ SET NEW.total:= va + vb;
+END;
+$$
+DELIMITER ;$$
+INSERT INTO t1 (a,b) VALUES (10, 20);
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test
index c7a066cc203..8895677b79f 100644
--- a/mysql-test/t/truncate.test
+++ b/mysql-test/t/truncate.test
@@ -56,7 +56,7 @@ drop table t1;
# Test for Bug#5507 "TRUNCATE should work with views"
#
# when it'll be fixed, the error should become 1347
-# (test.v1' is not BASE TABLE)
+# (test.v1' is not of type 'BASE TABLE')
#
create table t1 (s1 int);
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 11924f696db..7c4af618c23 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -369,12 +369,18 @@ select @a;
--echo #
--echo # BUG LP:1008487 virtual bool Item_cache::is_expensive(): Assertion `example' failed
--echo #
+SET TIMESTAMP=UNIX_TIMESTAMP('2017-01-03 00:00:00');
create table t1(a date,key(a));
insert into t1 values ('2012-01-01'),('2012-02-02');
explain
select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
+SET TIMESTAMP=UNIX_TIMESTAMP('2012-01-03 00:00:01');
+explain
+select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
+select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
drop table t1;
+SET TIMESTAMP=DEFAULT;
--echo #
--echo # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null
@@ -580,3 +586,22 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12721 Wrong execution plan for WHERE (date_field <=> timestamp_expr AND TRUE)
+--echo #
+CREATE TABLE t1(a DATE,KEY(a));
+INSERT INTO t1 VALUES ('2012-01-01'),('2012-02-02');
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP'2001-01-01 00:00:01' AND TRUE;
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP('2001-01-01', '00:00:01') AND TRUE;
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP'2001-01-01 00:00:00' AND TRUE;
+EXPLAIN SELECT 1 FROM t1 WHERE t1.a <=> TIMESTAMP('2001-01-01', '00:00:00') AND TRUE;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index 99c9bb656e6..b8029d616a5 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -751,3 +751,24 @@ DROP TABLE t1;
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-11331 Wrong result for INSERT INTO t1 (datetime_field) VALUES (hybrid_function_of_TIME_data_type)
+--echo #
+SET timestamp=UNIX_TIMESTAMP('2001-02-03 10:00:00');
+CREATE TABLE t1 (a DATETIME);
+INSERT INTO t1 VALUES (TIME'10:20:30');
+INSERT INTO t1 VALUES (COALESCE(TIME'10:20:30'));
+INSERT INTO t1 VALUES (LEAST(TIME'10:20:30',TIME'10:20:30'));
+SELECT * FROM t1;
+DROP TABLE t1;
+SET timestamp=DEFAULT;
+
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 777bb2f23e5..51fa3bb7461 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -612,3 +612,46 @@ select cast('-0.0' as decimal(5,1)) < 0;
--echo #
--echo # End of 5.5 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
+--echo #
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+--copy_file std_data/old_decimal/t1dec102.frm $MYSQLD_DATADIR/test/t1dec102.frm
+--copy_file std_data/old_decimal/t1dec102.MYD $MYSQLD_DATADIR/test/t1dec102.MYD
+--copy_file std_data/old_decimal/t1dec102.MYI $MYSQLD_DATADIR/test/t1dec102.MYI
+
+--echo # This creates the old DECIMAL. Will be fixed in MDEV-12574.
+CREATE TABLE t1 AS SELECT MAX(a) FROM t1dec102;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 AS SELECT COALESCE(a) FROM t1dec102;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BIGINT);
+CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a MEDIUMINT);
+CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a YEAR);
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1dec102;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+DROP TABLE t1dec102;
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index 105da427219..a79335960bc 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -179,10 +179,12 @@ DROP TABLE t1;
#
# Bug#28729: Field_enum wrongly reported an error while storing an empty string.
#
-create table t1(f1 set('a','b'), index(f1));
+SET sql_mode='';
+create table t1(f1 enum('a','b'), index(f1));
insert into t1 values(''),(''),('a'),('b');
select * from t1 where f1='';
drop table t1;
+SET sql_mode=DEFAULT;
#
# Bug#29360: Confluence of the special 0 enum value with the normal empty string
@@ -454,3 +456,65 @@ SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
ALTER TABLE t1 MODIFY a ENUM('2001','2002');
SELECT * FROM t1;
DROP TABLE t1;
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
+--echo #
+
+CREATE TABLE t1 (a ENUM('a','b','c','1'),KEY(a));
+INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
+EXPLAIN SELECT * FROM t1 WHERE a='xx';
+EXPLAIN SELECT * FROM t1 WHERE a='99999999';
+EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
+EXPLAIN SELECT * FROM t1 WHERE a=100;
+EXPLAIN SELECT * FROM t1 WHERE a=100.1;
+EXPLAIN SELECT * FROM t1 WHERE a='100';
+EXPLAIN SELECT * FROM t1 WHERE a='1x';
+EXPLAIN SELECT * FROM t1 WHERE a='1.0';
+EXPLAIN SELECT * FROM t1 WHERE a='1.1';
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
+--echo #
+
+CREATE TABLE t1 (a ENUM('a'));
+--echo # non-UNION + table column
+CREATE TABLE t2 AS SELECT (SELECT a FROM t1);
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+--echo # UNION + table column
+CREATE TABLE t2 AS SELECT (SELECT a FROM t1 UNION SELECT NULL);
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+--echo # UNION + SP variable
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va ENUM('a');
+ CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+--echo # UNION + anchored SP variable
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va TYPE OF t1.a;
+ CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
+ SHOW CREATE TABLE t2;
+ DROP TABLE t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+DROP TABLE t1;
diff --git a/mysql-test/t/type_set.test b/mysql-test/t/type_set.test
index 7a79cd12f70..8c26d5a4366 100644
--- a/mysql-test/t/type_set.test
+++ b/mysql-test/t/type_set.test
@@ -218,3 +218,25 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
+--echo #
+
+CREATE TABLE t1 (a SET('a','b','c','1'),KEY(a));
+INSERT INTO t1 VALUES ('a'),('b'),('c'),('1');
+EXPLAIN SELECT * FROM t1 WHERE a='xx';
+EXPLAIN SELECT * FROM t1 WHERE a='99999999';
+EXPLAIN SELECT * FROM t1 WHERE a=100.1e0;
+EXPLAIN SELECT * FROM t1 WHERE a=100;
+EXPLAIN SELECT * FROM t1 WHERE a=100.1;
+EXPLAIN SELECT * FROM t1 WHERE a='100';
+EXPLAIN SELECT * FROM t1 WHERE a='1x';
+EXPLAIN SELECT * FROM t1 WHERE a='1.0';
+EXPLAIN SELECT * FROM t1 WHERE a='1.1';
+DROP TABLE t1;
diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test
index fb96597e296..6662a3d9bb0 100644
--- a/mysql-test/t/type_time.test
+++ b/mysql-test/t/type_time.test
@@ -749,3 +749,19 @@ DROP TABLE t1,t2;
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
+--echo #
+SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31');
+SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
+CREATE TABLE t1 (a TIME);
+INSERT INTO t1 VALUES ('10:20:30'),('10:20:31'),('10:20:32');
+SELECT a FROM t1 WHERE a IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') ORDER BY a;
+DROP TABLE t1;
+SET timestamp=DEFAULT;
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index b90e122aa79..6d81a86331a 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -555,3 +555,54 @@ let defval='0000-00-00 00:00:00';
--echo #
--echo # End of 10.1 tests
--echo #
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-11333 MDEV-11333 Expect "Impossible where condition" for WHERE timestamp_field>=DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR)
+--echo #
+
+SELECT DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR);
+CREATE TABLE t1 (a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+INSERT INTO t1 VALUES('2001-01-01'),('2002-02-02'),('2003-03-03');
+EXPLAIN SELECT * FROM t1 WHERE a >= DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR);
+EXPLAIN SELECT * FROM t1 WHERE a >= COALESCE(DATE_ADD(TIMESTAMP'9999-01-01 00:00:00',INTERVAL 1000 YEAR));
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11482 Incorrect result for (time_expr BETWEEN timestamp_exp1 AND timestamp_expr2)
+--echo #
+SET @@sql_mode=DEFAULT;
+SET @@timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
+CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP);
+INSERT INTO t1 VALUES ('2001-01-01 00:00:00','2001-01-01 23:59:59');
+SELECT * FROM t1 WHERE TIME'10:20:30' BETWEEN a and b;
+DROP TABLE t1;
+SET @@timestamp=DEFAULT;
+
+--echo #
+--echo # MDEV-12582 Wrong data type for CREATE..SELECT MAX(COALESCE(timestamp_column))
+--echo #
+
+CREATE TABLE t1 (a TIMESTAMP);
+CREATE TABLE t2 AS SELECT
+ MAX(a),
+ COALESCE(a),
+ COALESCE(MAX(a)),
+ MAX(COALESCE(a))
+FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test
index 42a813b0782..c3a25c6bcce 100644
--- a/mysql-test/t/udf.test
+++ b/mysql-test/t/udf.test
@@ -25,7 +25,7 @@ eval CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO";
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO";
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
-eval CREATE FUNCTION sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO";
+eval CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO";
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
eval CREATE FUNCTION lookup RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
@@ -238,7 +238,7 @@ DROP FUNCTION myfunc_double;
--error ER_SP_DOES_NOT_EXIST
DROP FUNCTION myfunc_nonexist;
DROP FUNCTION myfunc_int;
-DROP FUNCTION sequence;
+DROP FUNCTION udf_sequence;
DROP FUNCTION lookup;
DROP FUNCTION reverse_lookup;
DROP FUNCTION avgcost;
@@ -401,19 +401,19 @@ DROP TABLE const_len_bug;
#
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
-eval CREATE FUNCTION sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO";
+eval CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO";
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT PRIMARY KEY);
INSERT INTO t1 VALUES (4),(3),(2),(1);
INSERT INTO t2 SELECT * FROM t1;
-SELECT sequence() AS seq, a FROM t1 ORDER BY seq ASC;
-SELECT sequence() AS seq, a FROM t1 ORDER BY seq DESC;
+SELECT udf_sequence() AS seq, a FROM t1 ORDER BY seq ASC;
+SELECT udf_sequence() AS seq, a FROM t1 ORDER BY seq DESC;
-SELECT * FROM t1 WHERE a = sequence();
-SELECT * FROM t2 WHERE a = sequence();
+SELECT * FROM t1 WHERE a = udf_sequence();
+SELECT * FROM t2 WHERE a = udf_sequence();
-DROP FUNCTION sequence;
+DROP FUNCTION udf_sequence;
DROP TABLE t1,t2;
#
diff --git a/mysql-test/t/udf_notembedded.test b/mysql-test/t/udf_notembedded.test
index bf54af7256c..d6658604005 100644
--- a/mysql-test/t/udf_notembedded.test
+++ b/mysql-test/t/udf_notembedded.test
@@ -5,10 +5,10 @@
# MDEV-8644 Using a UDF in a virtual column causes a crash when stopping the server
#
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
-eval create function sequence returns integer soname "$UDF_EXAMPLE_SO";
-create table t1 (n int key not null auto_increment, msg int as (sequence()) virtual);
+eval create function udf_sequence returns integer soname "$UDF_EXAMPLE_SO";
+create table t1 (n int key not null auto_increment, msg int as (udf_sequence()) virtual);
select * from t1;
source include/restart_mysqld.inc;
drop table t1;
-drop function sequence;
+drop function udf_sequence;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 359872d7e6d..abea52fe584 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -889,6 +889,22 @@ create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1;
show create table t2;
drop table t1, t2;
+CREATE TABLE t1
+(
+ c_varchar varchar(1) character set utf8 collate utf8_general_ci,
+ c_tinytext tinytext,
+ c_text text,
+ c_mediumtext mediumtext,
+ c_longtext longtext
+);
+CREATE TABLE t2 AS
+SELECT c_tinytext, c_text, c_mediumtext, c_longtext FROM t1
+UNION
+SELECT c_varchar, c_varchar, c_varchar, c_varchar FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
#
# Bug#18175: Union select over 129 tables with a sum function fails.
#
@@ -1508,7 +1524,6 @@ SELECT * FROM t1 t1_1 LEFT JOIN t1 t1_2 ON ( t1_2.b = t1_1.a )
DROP TABLE t1;
---echo #
--echo # Bug mdev-12788: UNION ALL + impossible having for derived
--echo # with IN subquery in WHERE
--echo #
@@ -1532,3 +1547,155 @@ eval $q;
eval EXPLAIN EXTENDED $q;
DROP TABLE t1,t2;
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12619 UNION creates excessive integer column types for integer literals
+--echo #
+
+CREATE TABLE t1 AS SELECT 1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE OR REPLACE TABLE t1 AS SELECT 1 UNION SELECT 1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE OR REPLACE TABLE t1 AS SELECT * FROM (SELECT 1 UNION SELECT 1) AS t0;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-9495 Wrong field type for a UNION of a signed and an unsigned INT expression
+--echo #
+CREATE TABLE t1 (a INT, b INT UNSIGNED);
+INSERT INTO t1 VALUES (0x7FFFFFFF,0xFFFFFFFF);
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1;
+SHOW CREATE TABLE t2;
+SELECT * FROM t2 ORDER BY a;
+DROP TABLE t2;
+CREATE TABLE t2 AS SELECT COALESCE(a,b), COALESCE(b,a) FROM t1;
+SHOW CREATE TABLE t2;
+SELECT * FROM t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-9497 UNION and COALESCE produce different field types for DECIMAL+INT
+--echo #
+CREATE TABLE t1 AS SELECT COALESCE(10.1,CAST(10 AS UNSIGNED)) AS a;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE OR REPLACE TABLE t1 AS SELECT 10.1 AS a UNION SELECT CAST(10 AS UNSIGNED);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-12594 UNION between fixed length double columns does not always preserve scale
+--echo #
+CREATE TABLE t1 (a FLOAT(20,4), b FLOAT(20,3), c FLOAT(20,4));
+INSERT INTO t1 VALUES (1111,2222,3333);
+
+CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE OR REPLACE TABLE t2 SELECT a FROM t1 UNION SELECT c FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE OR REPLACE TABLE t2 SELECT b FROM t1 UNION SELECT b FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE OR REPLACE TABLE t2 SELECT c FROM t1 UNION SELECT c FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE OR REPLACE TABLE t2 SELECT c FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE OR REPLACE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+CREATE OR REPLACE TABLE t2 AS SELECT b FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+
+DROP TABLE t1;
+
+--echo # Corner case
+CREATE TABLE t1 (a FLOAT(255,4), b FLOAT(255,3));
+INSERT INTO t1 VALUES (1111,2222);
+CREATE OR REPLACE TABLE t2 AS SELECT b FROM t1 UNION SELECT a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12595 UNION converts INT to BIGINT
+--echo #
+CREATE TABLE t1 AS SELECT
+ 1,
+ -1,
+ COALESCE(1,1),
+ COALESCE(-1,-1),
+ COALESCE(1,-1),
+ COALESCE(-1,1);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1 AS SELECT 1 AS c1,1 AS c2,-1 AS c3,-1 AS c4 UNION SELECT 1,-1,1,-1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-12599 UNION is not symmetric when mixing INT and CHAR
+--echo #
+
+CREATE OR REPLACE TABLE t1 AS SELECT 1 AS c1, 'a' AS c2 UNION SELECT 'a', 1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE OR REPLACE TABLE t1 AS SELECT 11112222 AS c1, 'a' AS c2 UNION SELECT 'a', 11112222;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+
+CREATE OR REPLACE TABLE t1 AS SELECT 111122223333 AS c1, 'a' AS c2 UNION SELECT 'a', 111122223333;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE OR REPLACE TABLE t1 AS SELECT 1111222233334444 AS c1, 'a' AS c2 UNION SELECT 'a', 1111222233334444;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT(3), b VARCHAR(1));
+CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BIGINT(3), b VARCHAR(1));
+CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BIGINT(12), b VARCHAR(1));
+CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
+SHOW CREATE TABLE t2;
+DROP TABLE t2;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 2c889c2cc0c..aae12ae4cbd 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -501,3 +501,18 @@ eval select $tmp < $tmp2;
--enable_column_names
--enable_query_log
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-12859 Out-of-range error for CREATE..SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM..
+--echo #
+
+SET sql_mode=STRICT_ALL_TABLES;
+CREATE OR REPLACE TABLE t1 AS
+SELECT @a:=EXTRACT(MINUTE_MICROSECOND FROM '2001-01-01 11:22:33.999999') AS c1;
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index ed6e92f145e..1ba20f0ac9e 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -438,9 +438,9 @@ select @a, @b;
#
# Bug#2586:Disallow global/session/local as structured var. instance names
#
---error ER_PARSE_ERROR
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
set @@global.global.key_buffer_size= 1;
---error ER_PARSE_ERROR
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
set GLOBAL global.key_buffer_size= 1;
--error ER_PARSE_ERROR
SELECT @@global.global.key_buffer_size;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 4430b65e5f4..00a040ccfdc 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -125,7 +125,7 @@ select * from v1;
select * from v2;
# try to drop nonexistent VIEW
--- error ER_BAD_TABLE_ERROR
+--error ER_UNKNOWN_VIEW
drop view v100;
# try to drop table with DROP VIEW
@@ -915,12 +915,6 @@ update v3 set v3.col1 = (select max(col1) from v2);
-- error ER_UPDATE_TABLE_USED
update v3 set v3.col1 = (select max(col1) from v3);
-- error ER_VIEW_PREVENT_UPDATE
-delete from v2 where col1 = (select max(col1) from v1);
--- error ER_VIEW_PREVENT_UPDATE
-delete from v2 where col1 = (select max(col1) from t1);
--- error ER_UPDATE_TABLE_USED
-delete from v2 where col1 = (select max(col1) from v2);
--- error ER_VIEW_PREVENT_UPDATE
delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
-- error ER_VIEW_PREVENT_UPDATE
delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
@@ -2124,12 +2118,24 @@ drop view abc;
#
# Bug#12993 View column rename broken in subselect
#
+
+flush status;
create table t1(f1 char(1));
create view v1 as select * from t1;
-select * from (select f1 as f2 from v1) v where v.f2='a';
+select * from (select f1 as f2, f1 as f3 from v1) v where v.f2='a';
+show status like "Created_tmp%";
drop view v1;
drop table t1;
+set @tmp=@@optimizer_switch;
+set @@optimizer_switch='derived_merge=OFF';
+create table t1(f1 char(1));
+create view v1 as select * from t1;
+select * from (select f1 as f2, f1 as f3 from v1) v where v.f2='a';
+show status like "Created_tmp%";
+drop view v1;
+drop table t1;
+set @@optimizer_switch=@tmp;
#
# Bug#11416 Server crash if using a view that uses function convert_tz
@@ -2782,7 +2788,7 @@ CREATE TABLE t1 (id INT);
CREATE VIEW v1 AS SELECT id FROM t1;
SHOW TABLES;
---error ER_BAD_TABLE_ERROR
+--error ER_UNKNOWN_VIEW
DROP VIEW v2,v1;
SHOW TABLES;
@@ -6271,3 +6277,19 @@ DROP VIEW v;
--echo #
--echo # End of 10.2 tests
--echo #
+
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-13197 Parser refactoring for CREATE VIEW,TRIGGER,SP,UDF,EVENT
+--echo #
+
+--error ER_PARSE_ERROR
+ALTER VIEW IF NOT EXISTS v1 AS SELECT 1;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test
index aff717e3151..753fe5c7693 100644
--- a/mysql-test/t/win.test
+++ b/mysql-test/t/win.test
@@ -1923,3 +1923,16 @@ insert into t1 values (1),(2),(10),(20),(30);
select sum(i) over (order by i), interval(sum(i) over (order by i), 10, 20)
from t1;
drop table t1;
+
+--echo #
+--echo # Start of 10.3 tests
+--echo #
+
+--echo #
+--echo # MDEV-13240 Wrong warning with MAX(datetime_field) OVER (...)
+--echo #
+
+CREATE TABLE t1 (dt DATETIME);
+INSERT INTO t1 VALUES ('2017-05-17');
+SELECT MAX(dt) OVER (ORDER BY dt ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/win_first_last_value.test b/mysql-test/t/win_first_last_value.test
index c7fd58472d8..0a90a98a5d4 100644
--- a/mysql-test/t/win_first_last_value.test
+++ b/mysql-test/t/win_first_last_value.test
@@ -75,3 +75,13 @@ select i,
from t1;
drop table t1;
+
+--echo #
+--echo # MDEV-12861 FIRST_VALUE() does not preserve the exact data type
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, c FLOAT);
+INSERT INTO t1 VALUES (1,1,1),(1,2,2),(2,1,1),(2,2,2);
+CREATE TABLE t2 AS SELECT a, FIRST_VALUE(b) OVER(), FIRST_VALUE(c) OVER() FROM t1 GROUP BY a;
+SHOW CREATE TABLE t2;
+DROP TABLE t2,t1;
diff --git a/mysql-test/t/win_insert_select.test b/mysql-test/t/win_insert_select.test
index 66df7324c4f..a9e7e8f322f 100644
--- a/mysql-test/t/win_insert_select.test
+++ b/mysql-test/t/win_insert_select.test
@@ -3,7 +3,7 @@ CREATE TABLE t1 (c1 INT, c2 VARCHAR(30));
PREPARE populate_table FROM "INSERT into t1 values (1, 'manual_insert_1'),
(4, 'manual_insert_2')";
-INSERT INTO t1 SELECT row_number() over(), "should_have_0" FROM t1;
+INSERT INTO t1 SELECT row_number() over(), "should_have_NULL" FROM t1;
INSERT INTO t1 SELECT 1 + row_number() over(), "should_have_2" FROM t1;
EXECUTE populate_table;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index 96a6e2ea1c2..74c755aa669 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -362,7 +362,6 @@
memory "loss" from _dl_init 2
Memcheck:Leak
fun:malloc
- fun:pool
...
fun:call_init*
fun:_dl_init
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 9916650308a..b8d9442fbc9 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -293,7 +293,7 @@ static void warn(const char *format,...)
{
void *frame[SF_REMEMBER_FRAMES + SF_FRAMES_SKIP];
int frames= backtrace(frame, array_elements(frame));
- fprintf(stderr, " ");
+ fprintf(stderr, " at ");
if (frames < SF_REMEMBER_FRAMES + SF_FRAMES_SKIP)
frame[frames]= 0;
print_stack(frame + SF_FRAMES_SKIP);
@@ -318,7 +318,8 @@ static int bad_ptr(const char *where, void *ptr)
}
if (irem->marker != MAGICSTART)
{
- warn("Error: %s unallocated data or underrun buffer", where);
+ DBUG_PRINT("error",("Unallocated data or underrun buffer %p", ptr));
+ warn("Error: %s unallocated data or underrun buffer %p", ptr, where);
return 1;
}
@@ -328,7 +329,8 @@ static int bad_ptr(const char *where, void *ptr)
magicend[2] != MAGICEND2 ||
magicend[3] != MAGICEND3)
{
- warn("Error: %s overrun buffer ", where);
+ DBUG_PRINT("error",("Overrun buffer %p", ptr));
+ warn("Error: %s overrun buffer %p", where);
fprintf(stderr, "Allocated at ");
print_stack(irem->frame);
return 1;
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 25113670015..98a1fa784a4 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -357,7 +357,8 @@ static void check_locks(THR_LOCK *lock, const char *where,
data && count < MAX_LOCKS;
data=data->next)
{
- if (data->type != TL_WRITE_CONCURRENT_INSERT)
+ if (data->type != TL_WRITE_CONCURRENT_INSERT &&
+ data->type != TL_WRITE_ALLOW_WRITE)
{
fprintf(stderr,
"Warning at '%s': Found TL_WRITE_CONCURRENT_INSERT lock mixed with other write lock: %d\n",
diff --git a/plugin/auth_examples/qa_auth_interface.c b/plugin/auth_examples/qa_auth_interface.c
index c9bc6c5aae4..b65acb5ea16 100644
--- a/plugin/auth_examples/qa_auth_interface.c
+++ b/plugin/auth_examples/qa_auth_interface.c
@@ -68,7 +68,7 @@ static int qa_auth_interface (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *inf
else if (strcmp(info->user_name, "qa_test_2_user")== 0)
{
/* Overwriting not intended, but with effect on USER() */
- strcpy(info->user_name, "user_name");
+ strcpy((char*) info->user_name, "user_name");
info->user_name_length= 9;
/* Overwriting not intended, effect not visible */
strcpy((char *)info->auth_string, "auth_string");
@@ -107,7 +107,7 @@ static int qa_auth_interface (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *inf
else if (strcmp(info->user_name, "qa_test_5_user")== 0)
{
/* This assignment has no effect.*/
- strcpy(info->user_name, "");
+ strcpy((char*) info->user_name, "");
info->user_name_length= 0;
/* This assignment has no effect.*/
strcpy((char *)info->auth_string, "");
diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc
index bd433efa4d3..81a08c8bdf0 100644
--- a/plugin/feedback/feedback.cc
+++ b/plugin/feedback/feedback.cc
@@ -93,8 +93,8 @@ static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter)
{
Item_cond_or *res= NULL;
Name_resolution_context nrc;
- const char *db= tables->db, *table= tables->alias,
- *field= tables->table->field[0]->field_name;
+ const char *db= tables->db, *table= tables->alias;
+ LEX_CSTRING *field= &tables->table->field[0]->field_name;
CHARSET_INFO *cs= &my_charset_latin1;
if (!filter->str)
diff --git a/plugin/handler_socket/handlersocket/database.cpp b/plugin/handler_socket/handlersocket/database.cpp
index 4292b826753..2ddff7689ad 100644
--- a/plugin/handler_socket/handlersocket/database.cpp
+++ b/plugin/handler_socket/handlersocket/database.cpp
@@ -1085,8 +1085,8 @@ dbcontext::parse_fields(TABLE *const table, const char *str,
Field **fld = 0;
size_t j = 0;
for (fld = table->field; *fld; ++fld, ++j) {
- DBG_FLD(fprintf(stderr, "f %s\n", (*fld)->field_name));
- string_ref fn((*fld)->field_name, strlen((*fld)->field_name));
+ DBG_FLD(fprintf(stderr, "f %s\n", (*fld)->field_name.str));
+ string_ref fn((*fld)->field_name.str, (*fld)->field_name.length);
if (fn == fldnms[i]) {
break;
}
@@ -1096,7 +1096,7 @@ dbcontext::parse_fields(TABLE *const table, const char *str,
std::string(fldnms[i].begin(), fldnms[i].size()).c_str()));
return false;
}
- DBG_FLD(fprintf(stderr, "FLD %s %zu\n", (*fld)->field_name, j));
+ DBG_FLD(fprintf(stderr, "FLD %s %zu\n", (*fld)->field_name.str, j));
flds.push_back(j);
}
return true;
diff --git a/plugin/qc_info/qc_info.cc b/plugin/qc_info/qc_info.cc
index e36e490dec3..b7d7e6f1f45 100644
--- a/plugin/qc_info/qc_info.cc
+++ b/plugin/qc_info/qc_info.cc
@@ -142,7 +142,7 @@ static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
size_t flags_length;
const char *key, *db;
size_t key_length, db_length;
- LEX_STRING sql_mode_str;
+ LEX_CSTRING sql_mode_str;
const String *tz;
CHARSET_INFO *cs_client;
CHARSET_INFO *cs_result;
diff --git a/plugin/simple_password_check/simple_password_check.c b/plugin/simple_password_check/simple_password_check.c
index 8b460c5ed9d..f1cd5aaf17f 100644
--- a/plugin/simple_password_check/simple_password_check.c
+++ b/plugin/simple_password_check/simple_password_check.c
@@ -23,7 +23,8 @@
static unsigned min_length, min_digits, min_letters, min_others;
-static int validate(MYSQL_LEX_STRING *username, MYSQL_LEX_STRING *password)
+static int validate(MYSQL_CONST_LEX_STRING *username,
+ MYSQL_CONST_LEX_STRING *password)
{
unsigned digits=0 , uppers=0 , lowers=0, others=0, length= password->length;
const char *ptr= password->str, *end= ptr + length;
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh
index 466bb46b382..466bb46b382 100644..100755
--- a/scripts/wsrep_sst_common.sh
+++ b/scripts/wsrep_sst_common.sh
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 7e7ed69ab46..88a4e40e373 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -48,6 +48,8 @@ ${WSREP_INCLUDES}
SET(GEN_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h
${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
+${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.h
+${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
)
SET(GEN_DIGEST_SOURCES
@@ -149,6 +151,7 @@ SET (SQL_SOURCE
sql_type.cc
item_windowfunc.cc sql_window.cc
sql_cte.cc
+ sql_sequence.cc sql_sequence.h ha_sequence.h
${WSREP_SOURCES}
table_cache.cc encryption.cc temporary_tables.cc
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
@@ -171,6 +174,8 @@ ENDIF()
MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY
RECOMPILE_FOR_EMBEDDED)
+MYSQL_ADD_PLUGIN(sql_sequence ha_sequence.cc STORAGE_ENGINE MANDATORY STATIC_ONLY
+RECOMPILE_FOR_EMBEDDED)
ADD_LIBRARY(sql STATIC ${SQL_SOURCE})
ADD_DEPENDENCIES(sql GenServerSource)
@@ -325,6 +330,14 @@ RUN_BISON(
${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy
${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h
+ MYSQL
+)
+
+RUN_BISON(
+ ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc_ora.yy
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.h
+ ORA
)
# Gen_lex_hash
@@ -377,6 +390,7 @@ CONFIGURE_FILE(
ADD_CUSTOM_TARGET(dist
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/make_dist.cmake
DEPENDS ${CMAKE_BINARY_DIR}/sql/sql_yacc.cc ${CMAKE_BINARY_DIR}/sql/sql_yacc.h
+ DEPENDS ${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.cc ${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.h
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
diff --git a/sql/create_options.cc b/sql/create_options.cc
index 99562faa077..a56357db588 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -119,7 +119,7 @@ static bool report_unknown_option(THD *thd, engine_option_value *val,
#define value_ptr(STRUCT,OPT) ((char*)(STRUCT) + (OPT)->offset)
static bool set_one_value(ha_create_table_option *opt,
- THD *thd, const LEX_STRING *value, void *base,
+ THD *thd, const LEX_CSTRING *value, void *base,
bool suppress_warning,
MEM_ROOT *root)
{
@@ -311,7 +311,7 @@ bool parse_option_list(THD* thd, handlerton *hton, void *option_struct_arg,
}
if (!seen || (opt->var && !last->value.str))
{
- LEX_STRING default_val= null_lex_str;
+ LEX_CSTRING default_val= null_clex_str;
/*
Okay, here's the logic for sysvar options:
@@ -320,8 +320,8 @@ bool parse_option_list(THD* thd, handlerton *hton, void *option_struct_arg,
*current* value of the underlying sysvar.
2. But only if the underlying sysvar value is different from the
sysvar's default.
- 3. If it's ALTER TABLE and the sysvar option was not explicitly
- mentioned - do nothing, do not add it to the list.
+ 3. If it's ALTER TABLE or CREATE_SEQUENCE and the sysvar option was
+ not explicitly mentioned - do nothing, do not add it to the list.
4. But if it was ALTER TABLE with sysvar option = DEFAULT, we
add it to the list (under the same condition #2).
5. If we're here parsing the option list from the .frm file
@@ -329,7 +329,6 @@ bool parse_option_list(THD* thd, handlerton *hton, void *option_struct_arg,
do not add it to the list (makes no sense anyway) and
use the *default* value of the underlying sysvar. Because
sysvar value can change, but it should not affect existing tables.
-
This is how it's implemented: the current sysvar value is added
to the list if suppress_warning is FALSE (meaning a table is created,
that is CREATE TABLE or ALTER TABLE) and it's actually a CREATE TABLE
@@ -349,9 +348,9 @@ bool parse_option_list(THD* thd, handlerton *hton, void *option_struct_arg,
{
char buf[256];
String sbuf(buf, sizeof(buf), system_charset_info), *str;
- if ((str= sysvar->val_str(&sbuf, thd, OPT_SESSION, &null_lex_str)))
+ if ((str= sysvar->val_str(&sbuf, thd, OPT_SESSION, &null_clex_str)))
{
- LEX_STRING name= { const_cast<char*>(opt->name), opt->name_length };
+ LEX_CSTRING name= { opt->name, opt->name_length };
default_val.str= strmake_root(root, str->ptr(), str->length());
default_val.length= str->length();
val= new (root) engine_option_value(name, default_val,
@@ -689,7 +688,7 @@ uchar *engine_option_value::frm_read(const uchar *buff, const uchar *buff_end,
engine_option_value **start,
engine_option_value **end, MEM_ROOT *root)
{
- LEX_STRING name, value;
+ LEX_CSTRING name, value;
uint len;
#define need_buff(N) if (buff + (N) >= buff_end) return NULL
diff --git a/sql/create_options.h b/sql/create_options.h
index 191ec88750a..41e8abcb232 100644
--- a/sql/create_options.h
+++ b/sql/create_options.h
@@ -29,8 +29,8 @@ enum { ENGINE_OPTION_MAX_LENGTH=32767 };
class engine_option_value: public Sql_alloc
{
public:
- LEX_STRING name;
- LEX_STRING value;
+ LEX_CSTRING name;
+ LEX_CSTRING value;
engine_option_value *next; ///< parser puts them in a FIFO linked list
bool parsed; ///< to detect unrecognized options
bool quoted_value; ///< option=VAL vs. option='VAL'
@@ -42,28 +42,30 @@ class engine_option_value: public Sql_alloc
{
link(start, end);
}
- engine_option_value(LEX_STRING &name_arg, LEX_STRING &value_arg, bool quoted,
+ engine_option_value(LEX_CSTRING &name_arg, LEX_CSTRING &value_arg,
+ bool quoted,
engine_option_value **start, engine_option_value **end) :
name(name_arg), value(value_arg),
next(NULL), parsed(false), quoted_value(quoted)
{
link(start, end);
}
- engine_option_value(LEX_STRING &name_arg,
+ engine_option_value(LEX_CSTRING &name_arg,
engine_option_value **start, engine_option_value **end) :
- name(name_arg), value(null_lex_str),
+ name(name_arg), value(null_clex_str),
next(NULL), parsed(false), quoted_value(false)
{
link(start, end);
}
- engine_option_value(LEX_STRING &name_arg, ulonglong value_arg,
+ engine_option_value(LEX_CSTRING &name_arg, ulonglong value_arg,
engine_option_value **start, engine_option_value **end,
MEM_ROOT *root) :
name(name_arg), next(NULL), parsed(false), quoted_value(false)
{
- if ((value.str= (char *)alloc_root(root, 22)))
+ char *str;
+ if ((value.str= str= (char *)alloc_root(root, 22)))
{
- value.length= longlong10_to_str(value_arg, value.str, 10) - value.str;
+ value.length= longlong10_to_str(value_arg, str, 10) - str;
link(start, end);
}
}
diff --git a/sql/datadict.cc b/sql/datadict.cc
index 103a33214ae..edc9fe5681b 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -18,6 +18,7 @@
#include "sql_priv.h"
#include "sql_class.h"
#include "sql_table.h"
+#include "ha_sequence.h"
static int read_string(File file, uchar**to, size_t length)
{
@@ -43,36 +44,43 @@ static int read_string(File file, uchar**to, size_t length)
@param[in] path path to FRM file.
@param[in/out] engine_name table engine name (length < NAME_CHAR_LEN)
- engine_name is a LEX_STRING, where engine_name->str must point to
+ engine_name is a LEX_CSTRING, where engine_name->str must point to
a buffer of at least NAME_CHAR_LEN+1 bytes.
- @retval FRMTYPE_ERROR error
- @retval FRMTYPE_TABLE table
- @retval FRMTYPE_VIEW view
+ @param[out] is_sequence 1 if table is a SEQUENCE, 0 otherwise
+
+ @retval TABLE_TYPE_UNKNOWN error
+ @retval TABLE_TYPE_TABLE table
+ @retval TABLE_TYPE_SEQUENCE sequence table
+ @retval TABLE_TYPE_VIEW view
*/
-frm_type_enum dd_frm_type(THD *thd, char *path, LEX_STRING *engine_name)
+Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
+ bool *is_sequence)
{
File file;
- uchar header[10]; //"TYPE=VIEW\n" it is 10 characters
+ uchar header[40]; //"TYPE=VIEW\n" it is 10 characters
size_t error;
- frm_type_enum type= FRMTYPE_ERROR;
+ Table_type type= TABLE_TYPE_UNKNOWN;
uchar dbt;
DBUG_ENTER("dd_frm_type");
- if ((file= mysql_file_open(key_file_frm, path, O_RDONLY | O_SHARE, MYF(0))) < 0)
- DBUG_RETURN(FRMTYPE_ERROR);
+ *is_sequence= 0;
+
+ if ((file= mysql_file_open(key_file_frm, path, O_RDONLY | O_SHARE, MYF(0)))
+ < 0)
+ DBUG_RETURN(TABLE_TYPE_UNKNOWN);
error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP));
if (error)
goto err;
- if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header)))
+ if (!strncmp((char*) header, "TYPE=VIEW\n", 10))
{
- type= FRMTYPE_VIEW;
+ type= TABLE_TYPE_VIEW;
goto err;
}
- type= FRMTYPE_TABLE;
+ type= TABLE_TYPE_NORMAL;
if (!is_binary_frm_header(header) || !engine_name)
goto err;
@@ -80,6 +88,12 @@ frm_type_enum dd_frm_type(THD *thd, char *path, LEX_STRING *engine_name)
engine_name->length= 0;
dbt= header[3];
+ if (((header[39] >> 4) & 3) == HA_CHOICE_YES)
+ {
+ DBUG_PRINT("info", ("Sequence found"));
+ *is_sequence= 1;
+ }
+
/* cannot use ha_resolve_by_legacy_type without a THD */
if (thd && dbt < DB_TYPE_FIRST_DYNAMIC)
{
@@ -121,8 +135,14 @@ frm_type_enum dd_frm_type(THD *thd, char *path, LEX_STRING *engine_name)
{
uint len= uint2korr(next_chunk);
if (len <= NAME_CHAR_LEN)
- strmake(engine_name->str, (char*)next_chunk + 2,
+ {
+ /*
+ The following cast is safe as the caller has allocated buffer
+ and it's up to this function to generate the name.
+ */
+ strmake((char*) engine_name->str, (char*)next_chunk + 2,
engine_name->length= len);
+ }
}
}
diff --git a/sql/datadict.h b/sql/datadict.h
index 9b180a882f9..e102618c2f7 100644
--- a/sql/datadict.h
+++ b/sql/datadict.h
@@ -1,6 +1,7 @@
#ifndef DATADICT_INCLUDED
#define DATADICT_INCLUDED
-/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, Oracle and/or its affiliates.
+ Copyright (c) 2017 MariaDB corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,11 +22,12 @@
Data dictionary API.
*/
-enum frm_type_enum
+enum Table_type
{
- FRMTYPE_ERROR= 0,
- FRMTYPE_TABLE,
- FRMTYPE_VIEW
+ TABLE_TYPE_UNKNOWN,
+ TABLE_TYPE_NORMAL, /* Normal table */
+ TABLE_TYPE_SEQUENCE,
+ TABLE_TYPE_VIEW
};
/*
@@ -35,11 +37,14 @@ enum frm_type_enum
Prefer to use ha_table_exists() instead.
To check whether it's an frm of a view, use dd_frm_is_view().
*/
-frm_type_enum dd_frm_type(THD *thd, char *path, LEX_STRING *engine_name);
+
+enum Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
+ bool *is_sequence);
static inline bool dd_frm_is_view(THD *thd, char *path)
{
- return dd_frm_type(thd, path, NULL) == FRMTYPE_VIEW;
+ bool not_used2;
+ return dd_frm_type(thd, path, NULL, &not_used2) == TABLE_TYPE_VIEW;
}
bool dd_recreate_table(THD *thd, const char *db, const char *table_name,
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 9e1ee6f30f9..2ab06fb34f2 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -171,13 +171,13 @@ Event_creation_ctx::load_from_db(THD *thd,
*/
bool
-Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n)
+Event_queue_element_for_exec::init(LEX_CSTRING db, LEX_CSTRING n)
{
if (!(dbname.str= my_strndup(db.str, dbname.length= db.length, MYF(MY_WME))))
return TRUE;
if (!(name.str= my_strndup(n.str, name.length= n.length, MYF(MY_WME))))
{
- my_free(dbname.str);
+ my_free(const_cast<char*>(dbname.str));
return TRUE;
}
return FALSE;
@@ -193,8 +193,8 @@ Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n)
Event_queue_element_for_exec::~Event_queue_element_for_exec()
{
- my_free(dbname.str);
- my_free(name.str);
+ my_free(const_cast<char*>(dbname.str));
+ my_free(const_cast<char*>(name.str));
}
@@ -233,7 +233,7 @@ Event_basic::~Event_basic()
/*
- Short function to load a char column into a LEX_STRING
+ Short function to load a char column into a LEX_CSTRING
SYNOPSIS
Event_basic::load_string_field()
@@ -249,7 +249,7 @@ Event_basic::load_string_fields(Field **fields, ...)
bool ret= FALSE;
va_list args;
enum enum_events_table_field field_name;
- LEX_STRING *field_value;
+ LEX_CSTRING *field_value;
DBUG_ENTER("Event_basic::load_string_fields");
@@ -257,7 +257,7 @@ Event_basic::load_string_fields(Field **fields, ...)
field_name= (enum enum_events_table_field) va_arg(args, int);
while (field_name < ET_FIELD_COUNT)
{
- field_value= va_arg(args, LEX_STRING *);
+ field_value= va_arg(args, LEX_CSTRING *);
if ((field_value->str= get_field(&mem_root, fields[field_name])) == NullS)
{
ret= TRUE;
@@ -274,9 +274,9 @@ Event_basic::load_string_fields(Field **fields, ...)
bool
-Event_basic::load_time_zone(THD *thd, const LEX_STRING tz_name)
+Event_basic::load_time_zone(THD *thd, const LEX_CSTRING *tz_name)
{
- String str(tz_name.str, &my_charset_latin1);
+ String str(tz_name->str, &my_charset_latin1);
time_zone= my_tz_find(thd, &str);
return (time_zone == NULL);
@@ -391,9 +391,9 @@ Event_timed::init()
bool
Event_job_data::load_from_row(THD *thd, TABLE *table)
{
- char *ptr;
+ const char *ptr;
size_t len;
- LEX_STRING tz_name;
+ LEX_CSTRING tz_name;
DBUG_ENTER("Event_job_data::load_from_row");
@@ -412,7 +412,7 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
ET_FIELD_COUNT))
DBUG_RETURN(TRUE);
- if (load_time_zone(thd, tz_name))
+ if (load_time_zone(thd, &tz_name))
DBUG_RETURN(TRUE);
Event_creation_ctx::load_from_db(thd, &mem_root, dbname.str, name.str, table,
@@ -452,9 +452,9 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
bool
Event_queue_element::load_from_row(THD *thd, TABLE *table)
{
- char *ptr;
+ const char *ptr;
MYSQL_TIME time;
- LEX_STRING tz_name;
+ LEX_CSTRING tz_name;
DBUG_ENTER("Event_queue_element::load_from_row");
@@ -472,7 +472,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
ET_FIELD_COUNT))
DBUG_RETURN(TRUE);
- if (load_time_zone(thd, tz_name))
+ if (load_time_zone(thd, &tz_name))
DBUG_RETURN(TRUE);
starts_null= table->field[ET_FIELD_STARTS]->is_null();
@@ -519,7 +519,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
int i;
char buff[MAX_FIELD_WIDTH];
String str(buff, sizeof(buff), &my_charset_bin);
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str);
if (!(tmp.length= str.length()))
@@ -590,7 +590,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
bool
Event_timed::load_from_row(THD *thd, TABLE *table)
{
- char *ptr;
+ const char *ptr;
size_t len;
DBUG_ENTER("Event_timed::load_from_row");
@@ -1203,7 +1203,7 @@ Event_timed::get_create_event(THD *thd, String *buf)
buf->append(STRING_WITH_LEN(" ON SCHEDULE EVERY "));
buf->append(expr_buf);
buf->append(' ');
- LEX_STRING *ival= &interval_type_to_name[interval];
+ LEX_CSTRING *ival= &interval_type_to_name[interval];
buf->append(ival->str, ival->length);
if (!starts_null)
@@ -1249,7 +1249,7 @@ Event_timed::get_create_event(THD *thd, String *buf)
bool
Event_job_data::construct_sp_sql(THD *thd, String *sp_sql)
{
- LEX_STRING buffer;
+ LEX_CSTRING buffer;
const uint STATIC_SQL_LENGTH= 44;
DBUG_ENTER("Event_job_data::construct_sp_sql");
@@ -1298,7 +1298,7 @@ Event_job_data::construct_sp_sql(THD *thd, String *sp_sql)
bool
Event_job_data::construct_drop_event_sql(THD *thd, String *sp_sql)
{
- LEX_STRING buffer;
+ LEX_CSTRING buffer;
const uint STATIC_SQL_LENGTH= 14;
DBUG_ENTER("Event_job_data::construct_drop_event_sql");
@@ -1426,7 +1426,13 @@ Event_job_data::execute(THD *thd, bool drop)
sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS;
sphead->m_flags|= sp_head::LOG_GENERAL_LOG;
- sphead->set_info(0, 0, &thd->lex->sp_chistics, sql_mode);
+ /*
+ construct_sp_sql() + parse_sql() set suid to SP_IS_NOT_SUID,
+ because we have the security context already set to the event
+ definer here. See more comments in construct_sp_sql().
+ */
+ DBUG_ASSERT(sphead->suid() == SP_IS_NOT_SUID);
+ sphead->m_sql_mode= sql_mode;
sphead->set_creation_ctx(creation_ctx);
sphead->optimize();
@@ -1478,7 +1484,7 @@ end:
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
}
- ret= Events::drop_event(thd, dbname, name, FALSE);
+ ret= Events::drop_event(thd, &dbname, &name, FALSE);
WSREP_TO_ISOLATION_END;
@@ -1519,9 +1525,9 @@ end:
*/
bool
-event_basic_db_equal(LEX_STRING db, Event_basic *et)
+event_basic_db_equal(const LEX_CSTRING *db, Event_basic *et)
{
- return !sortcmp_lex_string(et->dbname, db, system_charset_info);
+ return !sortcmp_lex_string(&et->dbname, db, system_charset_info);
}
@@ -1540,10 +1546,11 @@ event_basic_db_equal(LEX_STRING db, Event_basic *et)
*/
bool
-event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)
+event_basic_identifier_equal(const LEX_CSTRING *db, const LEX_CSTRING *name,
+ Event_basic *b)
{
- return !sortcmp_lex_string(name, b->name, system_charset_info) &&
- !sortcmp_lex_string(db, b->dbname, system_charset_info);
+ return !sortcmp_lex_string(name, &b->name, system_charset_info) &&
+ !sortcmp_lex_string(db, &b->dbname, system_charset_info);
}
/**
diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h
index 7ad8191f4d2..884bbd7d701 100644
--- a/sql/event_data_objects.h
+++ b/sql/event_data_objects.h
@@ -37,10 +37,10 @@ public:
~Event_queue_element_for_exec();
bool
- init(LEX_STRING dbname, LEX_STRING name);
+ init(LEX_CSTRING dbname, LEX_CSTRING name);
- LEX_STRING dbname;
- LEX_STRING name;
+ LEX_CSTRING dbname;
+ LEX_CSTRING name;
bool dropped;
THD *thd;
@@ -58,9 +58,9 @@ protected:
public:
- LEX_STRING dbname;
- LEX_STRING name;
- LEX_STRING definer;// combination of user and host
+ LEX_CSTRING dbname;
+ LEX_CSTRING name;
+ LEX_CSTRING definer;// combination of user and host
Time_zone *time_zone;
@@ -75,7 +75,7 @@ protected:
load_string_fields(Field **fields, ...);
bool
- load_time_zone(THD *thd, const LEX_STRING tz_name);
+ load_time_zone(THD *thd, const LEX_CSTRING *tz_name);
};
@@ -122,12 +122,12 @@ class Event_timed : public Event_queue_element
void operator=(Event_timed &);
public:
- LEX_STRING body;
+ LEX_CSTRING body;
- LEX_STRING definer_user;
- LEX_STRING definer_host;
+ LEX_CSTRING definer_user;
+ LEX_CSTRING definer_host;
- LEX_STRING comment;
+ LEX_CSTRING comment;
ulonglong created;
ulonglong modified;
@@ -135,7 +135,7 @@ public:
sql_mode_t sql_mode;
class Stored_program_creation_ctx *creation_ctx;
- LEX_STRING body_utf8;
+ LEX_CSTRING body_utf8;
Event_timed();
virtual ~Event_timed();
@@ -154,9 +154,9 @@ public:
class Event_job_data : public Event_basic
{
public:
- LEX_STRING body;
- LEX_STRING definer_user;
- LEX_STRING definer_host;
+ LEX_CSTRING body;
+ LEX_CSTRING definer_user;
+ LEX_CSTRING definer_host;
sql_mode_t sql_mode;
@@ -182,11 +182,12 @@ private:
/* Compares only the schema part of the identifier */
bool
-event_basic_db_equal(LEX_STRING db, Event_basic *et);
+event_basic_db_equal(const LEX_CSTRING *db, Event_basic *et);
/* Compares the whole identifier*/
bool
-event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b);
+event_basic_identifier_equal(const LEX_CSTRING *db, const LEX_CSTRING *name,
+ Event_basic *b);
/**
@} (End of group Event_Scheduler)
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index ca4d93eb240..e71cfdc1e16 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -368,14 +368,14 @@ mysql_event_fill_row(THD *thd,
if (rs)
{
- my_error(ER_EVENT_STORE_FAILED, MYF(0), fields[f_num]->field_name, rs);
+ my_error(ER_EVENT_STORE_FAILED, MYF(0), fields[f_num]->field_name.str, rs);
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
err_truncate:
- my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name);
+ my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name.str);
DBUG_RETURN(TRUE);
}
@@ -670,7 +670,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
parse_data->name.str));
DBUG_PRINT("info", ("check existance of an event with the same name"));
- if (!find_named_event(parse_data->dbname, parse_data->name, table))
+ if (!find_named_event(&parse_data->dbname, &parse_data->name, table))
{
if (thd->lex->create_info.or_replace())
{
@@ -768,8 +768,8 @@ end:
bool
Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
- LEX_STRING *new_dbname,
- LEX_STRING *new_name)
+ LEX_CSTRING *new_dbname,
+ LEX_CSTRING *new_name)
{
CHARSET_INFO *scs= system_charset_info;
TABLE *table= NULL;
@@ -802,7 +802,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
if (new_name)
{
DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
- if (!find_named_event(*new_dbname, *new_name, table))
+ if (!find_named_event(new_dbname, new_name, table))
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->str);
goto end;
@@ -814,7 +814,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
overwrite the key and SE will tell us that it cannot find the already found
row (copied into record[1] later
*/
- if (find_named_event(parse_data->dbname, parse_data->name, table))
+ if (find_named_event(&parse_data->dbname, &parse_data->name, table))
{
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), parse_data->name.str);
goto end;
@@ -878,7 +878,8 @@ end:
*/
bool
-Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
+Event_db_repository::drop_event(THD *thd, const LEX_CSTRING *db,
+ const LEX_CSTRING *name,
bool drop_if_exists)
{
TABLE *table= NULL;
@@ -891,7 +892,7 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
int ret= 1;
DBUG_ENTER("Event_db_repository::drop_event");
- DBUG_PRINT("enter", ("%s@%s", db.str, name.str));
+ DBUG_PRINT("enter", ("%s@%s", db->str, name->str));
if (open_event_table(thd, TL_WRITE, &table))
goto end;
@@ -906,13 +907,13 @@ Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
/* Event not found */
if (!drop_if_exists)
{
- my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
+ my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->str);
goto end;
}
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER_THD(thd, ER_SP_DOES_NOT_EXIST),
- "Event", name.str);
+ "Event", name->str);
ret= 0;
end:
@@ -939,12 +940,13 @@ end:
*/
bool
-Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
+Event_db_repository::find_named_event(const LEX_CSTRING *db,
+ const LEX_CSTRING *name,
TABLE *table)
{
uchar key[MAX_KEY_LENGTH];
DBUG_ENTER("Event_db_repository::find_named_event");
- DBUG_PRINT("enter", ("name: %.*s", (int) name.length, name.str));
+ DBUG_PRINT("enter", ("name: %.*s", (int) name->length, name->str));
/*
Create key to find row. We have to use field->store() to be able to
@@ -953,16 +955,16 @@ Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
'db' and 'name' and the first key is the primary key over the
same fields.
*/
- if (db.length > table->field[ET_FIELD_DB]->field_length ||
- name.length > table->field[ET_FIELD_NAME]->field_length ||
+ if (db->length > table->field[ET_FIELD_DB]->field_length ||
+ name->length > table->field[ET_FIELD_NAME]->field_length ||
table->s->keys == 0 ||
table->key_info[0].user_defined_key_parts != 2 ||
table->key_info[0].key_part[0].fieldnr != ET_FIELD_DB+1 ||
table->key_info[0].key_part[1].fieldnr != ET_FIELD_NAME+1)
DBUG_RETURN(TRUE);
- table->field[ET_FIELD_DB]->store(db.str, db.length, &my_charset_bin);
- table->field[ET_FIELD_NAME]->store(name.str, name.length, &my_charset_bin);
+ table->field[ET_FIELD_DB]->store(db->str, db->length, &my_charset_bin);
+ table->field[ET_FIELD_NAME]->store(name->str, name->length, &my_charset_bin);
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
@@ -989,7 +991,7 @@ Event_db_repository::find_named_event(LEX_STRING db, LEX_STRING name,
*/
void
-Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
+Event_db_repository::drop_schema_events(THD *thd, const LEX_CSTRING *schema)
{
int ret= 0;
TABLE *table= NULL;
@@ -997,7 +999,7 @@ Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
enum enum_events_table_field field= ET_FIELD_DB;
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
DBUG_ENTER("Event_db_repository::drop_schema_events");
- DBUG_PRINT("enter", ("field=%d schema=%s", field, schema.str));
+ DBUG_PRINT("enter", ("field: %d schema: %s", field, schema->str));
if (open_event_table(thd, TL_WRITE, &table))
DBUG_VOID_RETURN;
@@ -1013,12 +1015,12 @@ Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
/* et_field may be NULL if the table is corrupted or out of memory */
if (et_field)
{
- LEX_STRING et_field_lex= { et_field, strlen(et_field) };
+ LEX_CSTRING et_field_lex= { et_field, strlen(et_field) };
DBUG_PRINT("info", ("Current event %s name=%s", et_field,
get_field(thd->mem_root,
table->field[ET_FIELD_NAME])));
- if (!sortcmp_lex_string(et_field_lex, schema, system_charset_info))
+ if (!sortcmp_lex_string(&et_field_lex, schema, system_charset_info))
{
DBUG_PRINT("info", ("Dropping"));
if ((ret= table->file->ha_delete_row(table->record[0])))
@@ -1051,8 +1053,9 @@ end:
*/
bool
-Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
- LEX_STRING name, Event_basic *etn)
+Event_db_repository::load_named_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name,
+ Event_basic *etn)
{
bool ret;
ulonglong saved_mode= thd->variables.sql_mode;
@@ -1061,7 +1064,7 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
DBUG_ENTER("Event_db_repository::load_named_event");
DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd,
- (int) name.length, name.str));
+ (int) name->length, name->str));
event_table.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
@@ -1084,7 +1087,7 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
}
if ((ret= find_named_event(dbname, name, event_table.table)))
- my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
+ my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->str);
else if ((ret= etn->load_from_row(thd, event_table.table)))
my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event");
@@ -1106,8 +1109,8 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
bool
Event_db_repository::
update_timing_fields_for_event(THD *thd,
- LEX_STRING event_db_name,
- LEX_STRING event_name,
+ const LEX_CSTRING *event_db_name,
+ const LEX_CSTRING *event_name,
my_time_t last_executed,
ulonglong status)
{
@@ -1211,7 +1214,7 @@ Event_db_repository::check_system_tables(THD *thd)
else
{
if (tables.table->s->fields < event_priv_column_position ||
- strncmp(tables.table->field[event_priv_column_position]->field_name,
+ strncmp(tables.table->field[event_priv_column_position]->field_name.str,
STRING_WITH_LEN("Event_priv")))
{
sql_print_error("mysql.user has no `Event_priv` column at position %d",
diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h
index e7b52bacc2a..34de3ec2c45 100644
--- a/sql/event_db_repository.h
+++ b/sql/event_db_repository.h
@@ -77,20 +77,24 @@ public:
create_event(THD *thd, Event_parse_data *parse_data,
bool *event_already_exists);
bool
- update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname,
- LEX_STRING *new_name);
+ update_event(THD *thd, Event_parse_data *parse_data, LEX_CSTRING *new_dbname,
+ LEX_CSTRING *new_name);
bool
- drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists);
+ drop_event(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *name,
+ bool drop_if_exists);
void
- drop_schema_events(THD *thd, LEX_STRING schema);
+ drop_schema_events(THD *thd, const LEX_CSTRING *schema);
bool
- find_named_event(LEX_STRING db, LEX_STRING name, TABLE *table);
+ find_named_event(const LEX_CSTRING *db, const LEX_CSTRING *name,
+ TABLE *table);
bool
- load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
+ load_named_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name,
+ Event_basic *et);
static bool
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
@@ -100,8 +104,8 @@ public:
bool
update_timing_fields_for_event(THD *thd,
- LEX_STRING event_db_name,
- LEX_STRING event_name,
+ const LEX_CSTRING *event_db_name,
+ const LEX_CSTRING *event_name,
my_time_t last_executed,
ulonglong status);
public:
diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc
index 6c123c8e641..7932f228309 100644
--- a/sql/event_parse_data.cc
+++ b/sql/event_parse_data.cc
@@ -88,9 +88,6 @@ Event_parse_data::init_name(THD *thd, sp_name *spn)
name.length= spn->m_name.length;
name.str= thd->strmake(spn->m_name.str, spn->m_name.length);
- if (spn->m_qname.length == 0)
- spn->init_qname(thd);
-
DBUG_VOID_RETURN;
}
@@ -531,7 +528,7 @@ Event_parse_data::init_definer(THD *thd)
const char *definer_host= thd->lex->definer->host.str;
size_t definer_user_len= thd->lex->definer->user.length;
size_t definer_host_len= thd->lex->definer->host.length;
-
+ char *tmp;
DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx "
"definer_user: 0x%lx", (long) thd->mem_root,
(long) definer_user));
@@ -539,15 +536,14 @@ Event_parse_data::init_definer(THD *thd)
/* + 1 for @ */
DBUG_PRINT("info",("init definer as whole"));
definer.length= definer_user_len + definer_host_len + 1;
- definer.str= (char*) thd->alloc(definer.length + 1);
+ definer.str= tmp= (char*) thd->alloc(definer.length + 1);
DBUG_PRINT("info",("copy the user"));
- memcpy(definer.str, definer_user, definer_user_len);
- definer.str[definer_user_len]= '@';
+ strmake(tmp, definer_user, definer_user_len);
+ tmp[definer_user_len]= '@';
DBUG_PRINT("info",("copy the host"));
- memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len);
- definer.str[definer.length]= '\0';
+ strmake(tmp + definer_user_len + 1, definer_host, definer_host_len);
DBUG_PRINT("info",("definer [%s] initted", definer.str));
DBUG_VOID_RETURN;
diff --git a/sql/event_parse_data.h b/sql/event_parse_data.h
index 3ca7fcaab72..e1aed36aa01 100644
--- a/sql/event_parse_data.h
+++ b/sql/event_parse_data.h
@@ -66,10 +66,10 @@ public:
bool body_changed;
- LEX_STRING dbname;
- LEX_STRING name;
- LEX_STRING definer;// combination of user and host
- LEX_STRING comment;
+ LEX_CSTRING dbname;
+ LEX_CSTRING name;
+ LEX_CSTRING definer;// combination of user and host
+ LEX_CSTRING comment;
Item* item_starts;
Item* item_ends;
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index ae8ba258717..9ffb9935634 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -238,11 +238,13 @@ Event_queue::create_event(THD *thd, Event_queue_element *new_element,
*/
void
-Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
+Event_queue::update_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name,
Event_queue_element *new_element)
{
DBUG_ENTER("Event_queue::update_event");
- DBUG_PRINT("enter", ("thd: 0x%lx et=[%s.%s]", (long) thd, dbname.str, name.str));
+ DBUG_PRINT("enter", ("thd: %p et: [%s.%s]", thd, dbname->str,
+ name->str));
if ((new_element->status == Event_parse_data::DISABLED) ||
(new_element->status == Event_parse_data::SLAVESIDE_DISABLED))
@@ -287,11 +289,12 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
*/
void
-Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
+Event_queue::drop_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name)
{
DBUG_ENTER("Event_queue::drop_event");
- DBUG_PRINT("enter", ("thd: 0x%lx db :%s name: %s", (long) thd,
- dbname.str, name.str));
+ DBUG_PRINT("enter", ("thd: %p db: %s name: %s", thd,
+ dbname->str, name->str));
LOCK_QUEUE_DATA();
find_n_remove_event(dbname, name);
@@ -325,12 +328,12 @@ Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
*/
void
-Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
- bool (*comparator)(LEX_STRING, Event_basic *))
+Event_queue::drop_matching_events(THD *thd, const LEX_CSTRING *pattern,
+ bool (*comparator)(const LEX_CSTRING *, Event_basic *))
{
uint i;
DBUG_ENTER("Event_queue::drop_matching_events");
- DBUG_PRINT("enter", ("pattern=%s", pattern.str));
+ DBUG_PRINT("enter", ("pattern: %s", pattern->str));
for (i= queue_first_element(&queue) ;
i <= queue_last_element(&queue) ;
@@ -380,7 +383,7 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
*/
void
-Event_queue::drop_schema_events(THD *thd, LEX_STRING schema)
+Event_queue::drop_schema_events(THD *thd, const LEX_CSTRING *schema)
{
DBUG_ENTER("Event_queue::drop_schema_events");
LOCK_QUEUE_DATA();
@@ -404,7 +407,8 @@ Event_queue::drop_schema_events(THD *thd, LEX_STRING schema)
*/
void
-Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
+Event_queue::find_n_remove_event(const LEX_CSTRING *db,
+ const LEX_CSTRING *name)
{
uint i;
DBUG_ENTER("Event_queue::find_n_remove_event");
@@ -414,7 +418,7 @@ Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
i++)
{
Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
- DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db.str, name.str,
+ DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?", db->str, name->str,
et->dbname.str, et->name.str));
if (event_basic_identifier_equal(db, name, et))
{
@@ -683,7 +687,7 @@ end:
Event_db_repository *db_repository= Events::get_db_repository();
(void) db_repository->update_timing_fields_for_event(thd,
- (*event_name)->dbname, (*event_name)->name,
+ &(*event_name)->dbname, &(*event_name)->name,
last_executed, (ulonglong) status);
}
diff --git a/sql/event_queue.h b/sql/event_queue.h
index fdd5937ee17..ad3809fe086 100644
--- a/sql/event_queue.h
+++ b/sql/event_queue.h
@@ -31,7 +31,7 @@ extern PSI_cond_key key_COND_queue_state;
#endif /* HAVE_PSI_INTERFACE */
#include "queues.h" // QUEUE
-#include "sql_string.h" /* LEX_STRING */
+#include "sql_string.h" /* LEX_CSTRING */
#include "my_time.h" /* my_time_t, interval_type */
class Event_basic;
@@ -60,14 +60,14 @@ public:
bool *created);
void
- update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
+ update_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name,
Event_queue_element *new_element);
void
- drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
+ drop_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name);
void
- drop_schema_events(THD *thd, LEX_STRING schema);
+ drop_schema_events(THD *thd, const LEX_CSTRING *schema);
void
recalculate_activation_times(THD *thd);
@@ -98,12 +98,12 @@ private:
const char *src_func, const char *src_file, uint src_line);
void
- find_n_remove_event(LEX_STRING db, LEX_STRING name);
+ find_n_remove_event(const LEX_CSTRING *db, const LEX_CSTRING *name);
void
- drop_matching_events(THD *thd, LEX_STRING pattern,
- bool (*)(LEX_STRING, Event_basic *));
+ drop_matching_events(THD *thd, const LEX_CSTRING *pattern,
+ bool (*)(const LEX_CSTRING*, Event_basic *));
void
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 8ed5901b69a..c889cbeba67 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -301,7 +301,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
if (res)
goto end;
- if ((res= db_repository->load_named_event(thd, event->dbname, event->name,
+ if ((res= db_repository->load_named_event(thd, &event->dbname, &event->name,
&job_data)))
{
DBUG_PRINT("error", ("Got error from load_named_event"));
diff --git a/sql/events.cc b/sql/events.cc
index ecba97649b7..86e85d7f757 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -100,10 +100,11 @@ ulong Events::inited;
1 s > t
*/
-int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
+int sortcmp_lex_string(const LEX_CSTRING *s, const LEX_CSTRING *t,
+ const CHARSET_INFO *cs)
{
- return cs->coll->strnncollsp(cs, (uchar *) s.str,s.length,
- (uchar *) t.str,t.length);
+ return cs->coll->strnncollsp(cs, (uchar *) s->str, s->length,
+ (uchar *) t->str, t->length);
}
@@ -354,7 +355,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (thd->lex->create_info.or_replace() && event_queue)
- event_queue->drop_event(thd, parse_data->dbname, parse_data->name);
+ event_queue->drop_event(thd, &parse_data->dbname, &parse_data->name);
/* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->create_event(thd, parse_data,
@@ -367,12 +368,12 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
{
if (!(new_element= new Event_queue_element()))
ret= TRUE; // OOM
- else if ((ret= db_repository->load_named_event(thd, parse_data->dbname,
- parse_data->name,
+ else if ((ret= db_repository->load_named_event(thd, &parse_data->dbname,
+ &parse_data->name,
new_element)))
{
- if (!db_repository->drop_event(thd, parse_data->dbname,
- parse_data->name, TRUE))
+ if (!db_repository->drop_event(thd, &parse_data->dbname,
+ &parse_data->name, TRUE))
dropped= 1;
delete new_element;
}
@@ -440,7 +441,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
bool
Events::update_event(THD *thd, Event_parse_data *parse_data,
- LEX_STRING *new_dbname, LEX_STRING *new_name)
+ LEX_CSTRING *new_dbname, LEX_CSTRING *new_name)
{
int ret;
enum_binlog_format save_binlog_format;
@@ -470,9 +471,9 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (new_dbname) /* It's a rename */
{
/* Check that the new and the old names differ. */
- if ( !sortcmp_lex_string(parse_data->dbname, *new_dbname,
+ if ( !sortcmp_lex_string(&parse_data->dbname, new_dbname,
system_charset_info) &&
- !sortcmp_lex_string(parse_data->name, *new_name,
+ !sortcmp_lex_string(&parse_data->name, new_name,
system_charset_info))
{
my_error(ER_EVENT_SAME_NAME, MYF(0));
@@ -513,12 +514,12 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (!(ret= db_repository->update_event(thd, parse_data,
new_dbname, new_name)))
{
- LEX_STRING dbname= new_dbname ? *new_dbname : parse_data->dbname;
- LEX_STRING name= new_name ? *new_name : parse_data->name;
+ LEX_CSTRING dbname= new_dbname ? *new_dbname : parse_data->dbname;
+ LEX_CSTRING name= new_name ? *new_name : parse_data->name;
if (!(new_element= new Event_queue_element()))
ret= TRUE; // OOM
- else if ((ret= db_repository->load_named_event(thd, dbname, name,
+ else if ((ret= db_repository->load_named_event(thd, &dbname, &name,
new_element)))
delete new_element;
else
@@ -530,7 +531,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
it right away.
*/
if (event_queue)
- event_queue->update_event(thd, parse_data->dbname, parse_data->name,
+ event_queue->update_event(thd, &parse_data->dbname, &parse_data->name,
new_element);
/* Binlog the alter event. */
DBUG_ASSERT(thd->query() && thd->query_length());
@@ -568,7 +569,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
*/
bool
-Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
+Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name, bool if_exists)
{
int ret;
enum_binlog_format save_binlog_format;
@@ -577,7 +579,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
if (check_if_system_tables_error())
DBUG_RETURN(TRUE);
- if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0))
+ if (check_access(thd, EVENT_ACL, dbname->str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
/*
@@ -587,7 +589,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (lock_object_name(thd, MDL_key::EVENT,
- dbname.str, name.str))
+ dbname->str, name->str))
DBUG_RETURN(TRUE);
/* On error conditions my_error() is called so no need to handle here */
if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists)))
@@ -616,9 +618,9 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
*/
void
-Events::drop_schema_events(THD *thd, char *db)
+Events::drop_schema_events(THD *thd, const char *db)
{
- LEX_STRING const db_lex= { db, strlen(db) };
+ const LEX_CSTRING db_lex= { db, strlen(db) };
DBUG_ENTER("Events::drop_schema_events");
DBUG_PRINT("enter", ("dropping events from %s", db));
@@ -630,8 +632,8 @@ Events::drop_schema_events(THD *thd, char *db)
are damaged, as intended.
*/
if (event_queue)
- event_queue->drop_schema_events(thd, db_lex);
- db_repository->drop_schema_events(thd, db_lex);
+ event_queue->drop_schema_events(thd, &db_lex);
+ db_repository->drop_schema_events(thd, &db_lex);
DBUG_VOID_RETURN;
}
@@ -648,7 +650,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
char show_str_buf[10 * STRING_BUFFER_USUAL_SIZE];
String show_str(show_str_buf, sizeof(show_str_buf), system_charset_info);
List<Item> field_list;
- LEX_STRING sql_mode;
+ LEX_CSTRING sql_mode;
const String *tz_name;
MEM_ROOT *mem_root= thd->mem_root;
DBUG_ENTER("send_show_create_event");
@@ -731,18 +733,19 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol)
*/
bool
-Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
+Events::show_create_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name)
{
Event_timed et;
bool ret;
DBUG_ENTER("Events::show_create_event");
- DBUG_PRINT("enter", ("name: %s@%s", dbname.str, name.str));
+ DBUG_PRINT("enter", ("name: %s@%s", dbname->str, name->str));
if (check_if_system_tables_error())
DBUG_RETURN(TRUE);
- if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0))
+ if (check_access(thd, EVENT_ACL, dbname->str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
/*
@@ -783,8 +786,9 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
int
Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
{
- char *db= NULL;
+ const char *db= NULL;
int ret;
+ char db_tmp[SAFE_NAME_LEN];
DBUG_ENTER("Events::fill_schema_events");
/*
@@ -808,10 +812,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
check_access(thd, EVENT_ACL, thd->lex->select_lex.db,
NULL, NULL, 0, 0))
DBUG_RETURN(1);
- db= thd->lex->select_lex.db;
-
- if (lower_case_table_names)
- my_casedn_str(system_charset_info, db);
+ db= normalize_db_name(thd->lex->select_lex.db, db_tmp, sizeof(db_tmp));
}
ret= db_repository->fill_schema_events(thd, tables, db);
diff --git a/sql/events.h b/sql/events.h
index 368aa9a05d5..4b4505b6a02 100644
--- a/sql/events.h
+++ b/sql/events.h
@@ -36,7 +36,7 @@ extern PSI_stage_info stage_waiting_on_empty_queue;
extern PSI_stage_info stage_waiting_for_next_activation;
extern PSI_stage_info stage_waiting_for_scheduler_to_stop;
-#include "sql_string.h" /* LEX_STRING */
+#include "sql_string.h" /* LEX_CSTRING */
#include "my_time.h" /* interval_type */
class Event_db_repository;
@@ -48,7 +48,8 @@ class THD;
typedef class Item COND;
int
-sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
+sortcmp_lex_string(const LEX_CSTRING *s, const LEX_CSTRING *t,
+ const CHARSET_INFO *cs);
/**
@brief A facade to the functionality of the Event Scheduler.
@@ -109,16 +110,18 @@ public:
static bool
update_event(THD *thd, Event_parse_data *parse_data,
- LEX_STRING *new_dbname, LEX_STRING *new_name);
+ LEX_CSTRING *new_dbname, LEX_CSTRING *new_name);
static bool
- drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists);
+ drop_event(THD *thd, const LEX_CSTRING *dbname, const LEX_CSTRING *name,
+ bool if_exists);
static void
- drop_schema_events(THD *thd, char *db);
+ drop_schema_events(THD *thd, const char *db);
static bool
- show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
+ show_create_event(THD *thd, const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name);
/* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
static int
diff --git a/sql/field.cc b/sql/field.cc
index a872fab2520..6320121d1c3 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -51,15 +51,7 @@
*****************************************************************************/
static const char *zero_timestamp="0000-00-00 00:00:00.000000";
-
-/* number of bytes to store second_part part of the TIMESTAMP(N) */
-static uint sec_part_bytes[MAX_DATETIME_PRECISION+1]= { 0, 1, 1, 2, 2, 3, 3 };
-
-/* number of bytes to store DATETIME(N) */
-static uint datetime_hires_bytes[MAX_DATETIME_PRECISION+1]= { 5, 6, 6, 7, 7, 7, 8 };
-
-/* number of bytes to store TIME(N) */
-static uint time_hires_bytes[MAX_DATETIME_PRECISION+1]= { 3, 4, 4, 5, 5, 5, 6 };
+LEX_CSTRING temp_lex_str= {"temp", 4};
uchar Field_null::null[1]={1};
const char field_separator=',';
@@ -82,18 +74,35 @@ const char field_separator=',';
following #defines describe that gap and how to canculate number of fields
and index of field in this array.
*/
-#define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_BIT + 1)
-#define FIELDTYPE_TEAR_TO (MYSQL_TYPE_NEWDECIMAL - 1)
-#define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255 - FIELDTYPE_TEAR_TO))
+const int FIELDTYPE_TEAR_FROM= (MYSQL_TYPE_BIT + 1);
+const int FIELDTYPE_TEAR_TO= (MYSQL_TYPE_NEWDECIMAL - 1);
+const int FIELDTYPE_LAST= 254;
+const int FIELDTYPE_NUM= FIELDTYPE_TEAR_FROM + (FIELDTYPE_LAST -
+ FIELDTYPE_TEAR_TO);
+
static inline int field_type2index (enum_field_types field_type)
{
+ DBUG_ASSERT(real_type_to_type(field_type) < FIELDTYPE_TEAR_FROM ||
+ real_type_to_type(field_type) > FIELDTYPE_TEAR_TO);
+ DBUG_ASSERT(field_type <= FIELDTYPE_LAST);
field_type= real_type_to_type(field_type);
- return (field_type < FIELDTYPE_TEAR_FROM ?
- field_type :
- ((int)FIELDTYPE_TEAR_FROM) + (field_type - FIELDTYPE_TEAR_TO) - 1);
+ if (field_type < FIELDTYPE_TEAR_FROM)
+ return field_type;
+ return FIELDTYPE_TEAR_FROM + (field_type - FIELDTYPE_TEAR_TO) - 1;
}
+/**
+ Implements data type merge rules for the built-in traditional data types.
+ Used for operations such as:
+ - UNION
+ - CASE and its abbreviations COALESCE, IF, IFNULL
+ - LEAST/GREATEST
+
+ Given Fields A and B of real_types a and b, we find the result type of
+ COALESCE(A, B) by querying:
+ field_types_merge_rules[field_type_to_index(a)][field_type_to_index(b)].
+*/
static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
{
/* MYSQL_TYPE_DECIMAL -> */
@@ -107,7 +116,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
@@ -124,8 +133,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_TINY -> */
{
@@ -155,8 +164,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_SHORT -> */
{
@@ -186,8 +195,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_LONG -> */
{
@@ -217,8 +226,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_FLOAT -> */
{
@@ -248,8 +257,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_DOUBLE -> */
{
@@ -279,8 +288,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_NULL -> */
{
@@ -310,8 +319,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_TIMESTAMP -> */
{
@@ -341,8 +350,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_LONGLONG -> */
{
@@ -372,8 +381,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_INT24 -> */
{
@@ -403,8 +412,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_DATE -> */
{
@@ -434,8 +443,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_TIME -> */
{
@@ -465,8 +474,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_DATETIME -> */
{
@@ -496,13 +505,13 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_YEAR -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
+ MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_TINY,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
@@ -527,8 +536,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_NEWDATE -> */
{
@@ -558,8 +567,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_VARCHAR -> */
{
@@ -589,8 +598,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_BIT -> */
{
@@ -620,8 +629,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_NEWDECIMAL -> */
{
@@ -651,8 +660,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_ENUM -> */
{
@@ -682,8 +691,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_SET -> */
{
@@ -713,8 +722,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
},
/* MYSQL_TYPE_TINY_BLOB -> */
{
@@ -744,8 +753,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_TINY_BLOB
},
/* MYSQL_TYPE_MEDIUM_BLOB -> */
{
@@ -775,8 +784,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_MEDIUM_BLOB
},
/* MYSQL_TYPE_LONG_BLOB -> */
{
@@ -806,8 +815,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_LONG_BLOB
},
/* MYSQL_TYPE_BLOB -> */
{
@@ -837,8 +846,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_BLOB
},
/* MYSQL_TYPE_VAR_STRING -> */
{
@@ -868,8 +877,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_VARCHAR
},
/* MYSQL_TYPE_STRING -> */
{
@@ -899,39 +908,8 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
//MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_STRING
- },
- /* MYSQL_TYPE_GEOMETRY -> */
- {
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_BIT <16>-<245>
- MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY_BLOB,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY
+ //MYSQL_TYPE_STRING
+ MYSQL_TYPE_STRING
}
};
@@ -948,46 +926,19 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
enum_field_types Field::field_type_merge(enum_field_types a,
enum_field_types b)
{
- DBUG_ASSERT(real_type_to_type(a) < FIELDTYPE_TEAR_FROM ||
- real_type_to_type(a) > FIELDTYPE_TEAR_TO);
- DBUG_ASSERT(real_type_to_type(b) < FIELDTYPE_TEAR_FROM ||
- real_type_to_type(b) > FIELDTYPE_TEAR_TO);
return field_types_merge_rules[field_type2index(a)]
[field_type2index(b)];
}
-
-static Item_result field_types_result_type [FIELDTYPE_NUM]=
+const Type_handler *
+Type_handler::aggregate_for_result_traditional(const Type_handler *a,
+ const Type_handler *b)
{
- //MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
- DECIMAL_RESULT, INT_RESULT,
- //MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
- INT_RESULT, INT_RESULT,
- //MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
- REAL_RESULT, REAL_RESULT,
- //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- INT_RESULT, INT_RESULT,
- //MYSQL_TYPE_DATE MYSQL_TYPE_TIME
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
- STRING_RESULT, INT_RESULT,
- //MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_BIT <16>-<245>
- STRING_RESULT,
- //MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM
- DECIMAL_RESULT, STRING_RESULT,
- //MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING
- STRING_RESULT, STRING_RESULT,
- //MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY
- STRING_RESULT, STRING_RESULT
-};
+ enum_field_types ta= a->real_field_type();
+ enum_field_types tb= b->real_field_type();
+ return
+ Type_handler::get_handler_by_real_type(Field::field_type_merge(ta, tb));
+}
/*
@@ -1034,57 +985,11 @@ int compare(unsigned int a, unsigned int b)
CPP_UNNAMED_NS_END
-/**
- Detect Item_result by given field type of UNION merge result.
-
- @param field_type given field type
-
- @return
- Item_result (type of internal MySQL expression result)
-*/
-
-Item_result Field::result_merge_type(enum_field_types field_type)
-{
- DBUG_ASSERT(real_type_to_type(field_type) < FIELDTYPE_TEAR_FROM ||
- real_type_to_type(field_type) > FIELDTYPE_TEAR_TO);
- return field_types_result_type[field_type2index(field_type)];
-}
/*****************************************************************************
Static help functions
*****************************************************************************/
-/**
- Check whether a field type can be partially indexed by a key.
-
- This is a static method, rather than a virtual function, because we need
- to check the type of a non-Field in mysql_alter_table().
-
- @param type field type
-
- @retval
- TRUE Type can have a prefixed key
- @retval
- FALSE Type can not have a prefixed key
-*/
-
-bool Field::type_can_have_key_part(enum enum_field_types type)
-{
- switch (type) {
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_GEOMETRY:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
void Field::make_sort_key(uchar *buff,uint length)
{
@@ -1265,7 +1170,7 @@ bool Field::test_if_equality_guarantees_uniqueness(const Item *item) const
bool Field::can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal)
{
- DBUG_ASSERT(item_equal->compare_type() != STRING_RESULT);
+ DBUG_ASSERT(item_equal->compare_type_handler()->cmp_type() != STRING_RESULT);
DBUG_ASSERT(cmp_type() != STRING_RESULT);
switch (ctx.subst_constraint()) {
case ANY_SUBST:
@@ -1278,7 +1183,7 @@ bool Field::can_be_substituted_to_equal_item(const Context &ctx,
Items don't know the context they are in and there are functions like
IF (<hex_string>, 'yes', 'no').
*/
- return ctx.compare_type() == item_equal->compare_type();
+ return ctx.compare_type_handler() == item_equal->compare_type_handler();
case IDENTITY_SUBST:
return true;
}
@@ -1311,14 +1216,14 @@ bool Field::can_optimize_group_min_max(const Item_bool_func *cond,
/*
- This covers all numeric types, ENUM, SET, BIT
+ This covers all numeric types, BIT
*/
bool Field::can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const
{
DBUG_ASSERT(cmp_type() != TIME_RESULT); // Handled in Field_temporal
- DBUG_ASSERT(cmp_type() != STRING_RESULT); // Handled in Field_longstr
+ DBUG_ASSERT(cmp_type() != STRING_RESULT); // Handled in Field_str descendants
return item->cmp_type() != TIME_RESULT;
}
@@ -1353,7 +1258,7 @@ warn:
*/
Field_num::Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg),
@@ -1394,7 +1299,7 @@ Item *Field_num::get_equal_zerofill_const_item(THD *thd, const Context &ctx,
break;
}
DBUG_ASSERT(const_item->const_item());
- DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
+ DBUG_ASSERT(ctx.compare_type_handler()->cmp_type() != STRING_RESULT);
return const_item;
}
@@ -1683,9 +1588,9 @@ String *Field::val_int_as_str(String *val_buffer, bool unsigned_val)
/// This is used as a table name when the table structure is not set up
Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
- utype unireg_check_arg, const char *field_name_arg)
+ utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
:ptr(ptr_arg), null_ptr(null_ptr_arg), table(0), orig_table(0),
- table_name(0), field_name(field_name_arg), option_list(0),
+ table_name(0), field_name(*field_name_arg), option_list(0),
option_struct(0), key_start(0), part_of_key(0),
part_of_key_not_clustered(0), part_of_sortkey(0),
unireg_check(unireg_check_arg), field_length(length_arg),
@@ -1944,10 +1849,9 @@ void Field::make_field(Send_field *field)
else
{
field->table_name= "";
- field->org_col_name= "";
+ field->org_col_name= empty_clex_str;
}
field->col_name= field_name;
- field->charsetnr= charset()->number;
field->length=field_length;
field->type=type();
field->flags=table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
@@ -2052,21 +1956,22 @@ bool Field_num::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
longlong nr= val_int();
bool neg= !(flags & UNSIGNED_FLAG) && nr < 0;
return int_to_datetime_with_warn(neg, neg ? -nr : nr, ltime, fuzzydate,
- field_name);
+ field_name.str);
}
Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg, CHARSET_INFO *charset_arg)
+ const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
{
- field_charset= charset_arg;
- if (charset_arg->state & MY_CS_BINSORT)
+ field_charset= collation.collation;
+ if (collation.collation->state & MY_CS_BINSORT)
flags|=BINARY_FLAG;
- field_derivation= DERIVATION_IMPLICIT;
- field_repertoire= my_charset_repertoire(charset_arg);
+ field_derivation= collation.derivation;
+ field_repertoire= collation.repertoire;
}
@@ -2099,11 +2004,11 @@ bool Field_str::test_if_equality_guarantees_uniqueness(const Item *item) const
bool Field_str::can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal)
{
- DBUG_ASSERT(item_equal->compare_type() == STRING_RESULT);
+ DBUG_ASSERT(item_equal->compare_type_handler()->cmp_type() == STRING_RESULT);
switch (ctx.subst_constraint()) {
case ANY_SUBST:
- return ctx.compare_type() == item_equal->compare_type() &&
- (ctx.compare_type() != STRING_RESULT ||
+ return ctx.compare_type_handler() == item_equal->compare_type_handler() &&
+ (ctx.compare_type_handler()->cmp_type() != STRING_RESULT ||
ctx.compare_collation() == item_equal->compare_collation());
case IDENTITY_SUBST:
return ((charset()->state & MY_CS_BINSORT) &&
@@ -2953,7 +2858,7 @@ Field_new_decimal::Field_new_decimal(uchar *ptr_arg,
uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
uint8 dec_arg,bool zero_arg,
bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
@@ -2967,68 +2872,6 @@ Field_new_decimal::Field_new_decimal(uchar *ptr_arg,
}
-Field_new_decimal::Field_new_decimal(uint32 len_arg,
- bool maybe_null_arg,
- const char *name,
- uint8 dec_arg,
- bool unsigned_arg)
- :Field_num((uchar*) 0, len_arg,
- maybe_null_arg ? (uchar*) "": 0, 0,
- NONE, name, dec_arg, 0, unsigned_arg)
-{
- precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
- set_if_smaller(precision, DECIMAL_MAX_PRECISION);
- DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
- (dec <= DECIMAL_MAX_SCALE));
- bin_size= my_decimal_get_binary_size(precision, dec);
-}
-
-
-Field *Field_new_decimal::create_from_item(MEM_ROOT *mem_root, Item *item)
-{
- uint8 dec= item->decimals;
- uint8 intg= item->decimal_precision() - dec;
- uint32 len= item->max_char_length();
-
- DBUG_ASSERT (item->result_type() == DECIMAL_RESULT);
-
- /*
- Trying to put too many digits overall in a DECIMAL(prec,dec)
- will always throw a warning. We must limit dec to
- DECIMAL_MAX_SCALE however to prevent an assert() later.
- */
-
- if (dec > 0)
- {
- signed int overflow;
-
- dec= MY_MIN(dec, DECIMAL_MAX_SCALE);
-
- /*
- If the value still overflows the field with the corrected dec,
- we'll throw out decimals rather than integers. This is still
- bad and of course throws a truncation warning.
- +1: for decimal point
- */
-
- const int required_length=
- my_decimal_precision_to_length(intg + dec, dec,
- item->unsigned_flag);
-
- overflow= required_length - len;
-
- if (overflow > 0)
- dec= MY_MAX(0, dec - overflow); // too long, discard fract
- else
- /* Corrected value fits. */
- len= required_length;
- }
- return new (mem_root)
- Field_new_decimal(len, item->maybe_null, item->name,
- dec, item->unsigned_flag);
-}
-
-
int Field_new_decimal::reset(void)
{
store_value(&decimal_zero);
@@ -3329,7 +3172,7 @@ bool Field_new_decimal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
my_decimal value;
return decimal_to_datetime_with_warn(val_decimal(&value),
- ltime, fuzzydate, field_name);
+ ltime, fuzzydate, field_name.str);
}
@@ -3411,7 +3254,7 @@ bool Field_new_decimal::compatible_field_size(uint field_metadata,
uint Field_new_decimal::is_equal(Create_field *new_field)
{
- return ((new_field->sql_type == real_type()) &&
+ return ((new_field->type_handler() == type_handler()) &&
((new_field->flags & UNSIGNED_FLAG) ==
(uint) (flags & UNSIGNED_FLAG)) &&
((new_field->flags & AUTO_INCREMENT_FLAG) ==
@@ -3499,7 +3342,8 @@ Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx,
Field_time::get_equal_const_item().
*/
my_decimal_round(E_DEC_FATAL_ERROR, val, decimals(), true, &val_buffer2);
- return new (thd->mem_root) Item_decimal(thd, field_name, &val_buffer2,
+ return new (thd->mem_root) Item_decimal(thd, field_name.str,
+ &val_buffer2,
decimals(), field_length);
}
break;
@@ -4791,7 +4635,7 @@ bool Field_real::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
{
ASSERT_COLUMN_MARKED_FOR_READ;
double nr= val_real();
- return double_to_datetime_with_warn(nr, ltime, fuzzydate, field_name);
+ return double_to_datetime_with_warn(nr, ltime, fuzzydate, field_name.str);
}
@@ -4946,7 +4790,7 @@ void Field_double::sql_type(String &res) const
Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share)
:Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
@@ -5373,14 +5217,14 @@ static longlong read_bigendian(const uchar *from, uint bytes)
void Field_timestamp_hires::store_TIME(my_time_t timestamp, ulong sec_part)
{
mi_int4store(ptr, timestamp);
- store_bigendian(sec_part_shift(sec_part, dec), ptr+4, sec_part_bytes[dec]);
+ store_bigendian(sec_part_shift(sec_part, dec), ptr+4, sec_part_bytes(dec));
}
my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos,
ulong *sec_part) const
{
ASSERT_COLUMN_MARKED_FOR_READ;
- *sec_part= (long)sec_part_unshift(read_bigendian(pos+4, sec_part_bytes[dec]), dec);
+ *sec_part= (long)sec_part_unshift(read_bigendian(pos+4, sec_part_bytes(dec)), dec);
return mi_uint4korr(pos);
}
@@ -5447,19 +5291,14 @@ int Field_timestamp_hires::cmp(const uchar *a_ptr, const uchar *b_ptr)
int32 a,b;
ulong a_sec_part, b_sec_part;
a= mi_uint4korr(a_ptr);
- a_sec_part= (ulong)read_bigendian(a_ptr+4, sec_part_bytes[dec]);
+ a_sec_part= (ulong)read_bigendian(a_ptr+4, sec_part_bytes(dec));
b= mi_uint4korr(b_ptr);
- b_sec_part= (ulong)read_bigendian(b_ptr+4, sec_part_bytes[dec]);
+ b_sec_part= (ulong)read_bigendian(b_ptr+4, sec_part_bytes(dec));
return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 :
a_sec_part < b_sec_part ? -1 : a_sec_part > b_sec_part ? 1 : 0;
}
-uint32 Field_timestamp_hires::pack_length() const
-{
- return 4 + sec_part_bytes[dec];
-}
-
void Field_timestamp_with_dec::make_field(Send_field *field)
{
Field::make_field(field);
@@ -5494,7 +5333,7 @@ my_time_t Field_timestampf::get_timestamp(const uchar *pos,
/*************************************************************/
uint Field_temporal::is_equal(Create_field *new_field)
{
- return new_field->sql_type == real_type() &&
+ return new_field->type_handler() == type_handler() &&
new_field->length == max_display_length();
}
@@ -5906,7 +5745,7 @@ bool Field_time::check_zero_in_date_with_warn(ulonglong fuzzydate)
THD *thd= get_thd();
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
- ER_THD(thd, ER_WARN_DATA_OUT_OF_RANGE), field_name,
+ ER_THD(thd, ER_WARN_DATA_OUT_OF_RANGE), field_name.str,
thd->get_stmt_da()->current_row_for_warning());
return true;
}
@@ -6006,6 +5845,39 @@ int Field_time::store_decimal(const my_decimal *d)
}
+bool Field_time::can_be_substituted_to_equal_item(const Context &ctx,
+ const Item_equal *item_equal)
+{
+ DBUG_ASSERT(item_equal->compare_type_handler()->cmp_type() != STRING_RESULT);
+ switch (ctx.subst_constraint()) {
+ case ANY_SUBST:
+ /*
+ A TIME field in a DATETIME comparison can be substituted to
+ Item_equal with TIME comparison.
+
+ SET timestamp=UNIX_TIMESTAMP('2015-08-30 10:20:30');
+ CREATE OR REPLACE TABLE t1 (a TIME);
+ INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
+ SELECT * FROM t1 WHERE a>=TIMESTAMP'2015-08-30 00:00:00'
+ AND a='00:00:00';
+
+ The above query can be simplified to:
+ SELECT * FROM t1 WHERE TIME'00:00:00'>=TIMESTAMP'2015-08-30 00:00:00'
+ AND a='00:00:00';
+ And further to:
+ SELECT * FROM t1 WHERE a=TIME'00:00:00';
+ */
+ if (ctx.compare_type_handler() == &type_handler_datetime &&
+ item_equal->compare_type_handler() == &type_handler_time)
+ return true;
+ return ctx.compare_type_handler() == item_equal->compare_type_handler();
+ case IDENTITY_SUBST:
+ return true;
+ }
+ return false;
+}
+
+
Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
Item *const_item)
{
@@ -6065,11 +5937,6 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
}
-uint32 Field_time_hires::pack_length() const
-{
- return time_hires_bytes[dec];
-}
-
longlong Field_time_with_dec::val_int(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
@@ -6287,7 +6154,7 @@ bool Field_year::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
if (tmp || field_length != 4)
tmp+= 1900;
return int_to_datetime_with_warn(false, tmp * 10000,
- ltime, fuzzydate, field_name);
+ ltime, fuzzydate, field_name.str);
}
@@ -6772,11 +6639,6 @@ bool Field_datetime_hires::get_TIME(MYSQL_TIME *ltime, const uchar *pos,
}
-uint32 Field_datetime_hires::pack_length() const
-{
- return datetime_hires_bytes[dec];
-}
-
int Field_datetime_hires::cmp(const uchar *a_ptr, const uchar *b_ptr)
{
ulonglong a=read_bigendian(a_ptr, Field_datetime_hires::pack_length());
@@ -6967,15 +6829,15 @@ int Field_str::store(double nr)
uint Field::is_equal(Create_field *new_field)
{
- return (new_field->sql_type == real_type());
+ return new_field->type_handler() == type_handler();
}
uint Field_str::is_equal(Create_field *new_field)
{
- return ((new_field->sql_type == real_type()) &&
- new_field->charset == field_charset &&
- new_field->length == max_display_length());
+ return new_field->type_handler() == type_handler() &&
+ new_field->charset == field_charset &&
+ new_field->length == max_display_length();
}
@@ -7143,7 +7005,7 @@ check_field_for_37426(const void *param_arg)
Check_field_param *param= (Check_field_param*) param_arg;
DBUG_ASSERT(param->field->real_type() == MYSQL_TYPE_STRING);
DBUG_PRINT("debug", ("Field %s - type: %d, size: %d",
- param->field->field_name,
+ param->field->field_name.str,
param->field->real_type(),
param->field->row_pack_length()));
return param->field->row_pack_length() > 255;
@@ -7225,7 +7087,8 @@ uchar *Field_string::pack(uchar *to, const uchar *from, uint max_length)
{
uint length= MY_MIN(field_length,max_length);
uint local_char_length= max_length/field_charset->mbmaxlen;
- DBUG_PRINT("debug", ("Packing field '%s' - length: %u ", field_name, length));
+ DBUG_PRINT("debug", ("Packing field '%s' - length: %u ", field_name.str,
+ length));
if (length > local_char_length)
local_char_length= my_charpos(field_charset, from, from+length,
@@ -7397,7 +7260,7 @@ Field *Field_string::make_new_field(MEM_ROOT *root, TABLE *new_table,
if (type() != MYSQL_TYPE_VAR_STRING || keep_type)
field= Field::make_new_field(root, new_table, keep_type);
else if ((field= new (root) Field_varstring(field_length, maybe_null(),
- field_name,
+ &field_name,
new_table->s, charset())))
{
/*
@@ -7832,7 +7695,7 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table,
uint Field_varstring::is_equal(Create_field *new_field)
{
- if (new_field->sql_type == real_type() &&
+ if (new_field->type_handler() == type_handler() &&
new_field->charset == field_charset)
{
if (new_field->length == max_display_length())
@@ -7868,12 +7731,13 @@ void Field_varstring::hash(ulong *nr, ulong *nr2)
****************************************************************************/
Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg,
+ const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint blob_pack_length,
- CHARSET_INFO *cs)
+ const DTCollation &collation)
:Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
- cs),
+ collation),
packlength(blob_pack_length)
{
DBUG_ASSERT(blob_pack_length <= 4); // Only pack lengths 1-4 supported currently
@@ -8222,8 +8086,10 @@ Field *Field_blob::new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_null_ptr, uint new_null_bit)
{
Field_varstring *res= new (root) Field_varstring(new_ptr, length, 2,
- new_null_ptr, new_null_bit, Field::NONE,
- field_name, table->s, charset());
+ new_null_ptr,
+ new_null_bit, Field::NONE,
+ &field_name,
+ table->s, charset());
res->init(new_table);
return res;
}
@@ -8288,6 +8154,22 @@ void Field_blob::sort_string(uchar *to,uint length)
}
+/*
+ Return the data type handler, according to packlength.
+ Implemented in field.cc rather than in field.h
+ to avoid exporting type_handler_xxx with MYSQL_PLUGIN_IMPORT.
+*/
+const Type_handler *Field_blob::type_handler() const
+{
+ switch (packlength) {
+ case 1: return &type_handler_tiny_blob;
+ case 2: return &type_handler_blob;
+ case 3: return &type_handler_medium_blob;
+ }
+ return &type_handler_long_blob;
+}
+
+
void Field_blob::sql_type(String &res) const
{
const char *str;
@@ -8388,9 +8270,9 @@ uint Field_blob::max_packed_col_length(uint max_length)
uint Field_blob::is_equal(Create_field *new_field)
{
- return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
- && new_field->charset == field_charset &&
- new_field->pack_length == pack_length());
+ return new_field->type_handler() == type_handler() &&
+ new_field->charset == field_charset &&
+ new_field->pack_length == pack_length();
}
@@ -8417,7 +8299,7 @@ uint gis_field_options_image(uchar *buff, List<Create_field> &create_fields)
Create_field *field;
while ((field= it++))
{
- if (field->sql_type != MYSQL_TYPE_GEOMETRY)
+ if (field->real_field_type() != MYSQL_TYPE_GEOMETRY)
continue;
if (buff)
{
@@ -8574,7 +8456,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0),
Geometry::ci_collection[geom_type]->m_name.str,
Geometry::ci_collection[wkb_type]->m_name.str,
- field_name,
+ field_name.str,
(ulong) table->in_use->get_stmt_da()->
current_row_for_warning());
goto err_exit;
@@ -8610,7 +8492,7 @@ Field::geometry_type Field_geom::geometry_type_merge(geometry_type a,
uint Field_geom::is_equal(Create_field *new_field)
{
- return new_field->sql_type == MYSQL_TYPE_GEOMETRY &&
+ return new_field->type_handler() == type_handler() &&
/*
- Allow ALTER..INPLACE to supertype (GEOMETRY),
e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
@@ -8689,12 +8571,16 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1);
+ err= 1;
}
- if (!get_thd()->count_cuted_fields)
+ if (!get_thd()->count_cuted_fields && !length)
err= 0;
}
else
+ {
set_warning(WARN_DATA_TRUNCATED, 1);
+ err= 1;
+ }
}
store_type((ulonglong) tmp);
return err;
@@ -8868,6 +8754,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
tmp=0;
set_warning(WARN_DATA_TRUNCATED, 1);
+ err= 1;
}
}
else if (got_warning)
@@ -9032,7 +8919,7 @@ uint Field_enum::is_equal(Create_field *new_field)
The fields are compatible if they have the same flags,
type, charset and have the same underlying length.
*/
- if (new_field->sql_type != real_type() ||
+ if (new_field->type_handler() != type_handler() ||
new_field->charset != field_charset ||
new_field->pack_length != pack_length())
return IS_EQUAL_NO;
@@ -9097,7 +8984,7 @@ bool Field_num::eq_def(const Field *field) const
uint Field_num::is_equal(Create_field *new_field)
{
- return ((new_field->sql_type == real_type()) &&
+ return ((new_field->type_handler() == type_handler()) &&
((new_field->flags & UNSIGNED_FLAG) ==
(uint) (flags & UNSIGNED_FLAG)) &&
((new_field->flags & AUTO_INCREMENT_FLAG) ==
@@ -9106,12 +8993,17 @@ uint Field_num::is_equal(Create_field *new_field)
}
+bool Field_enum::can_optimize_range(const Item_bool_func *cond,
+ const Item *item,
+ bool is_eq_func) const
+{
+ return item->cmp_type() != TIME_RESULT;
+}
+
+
bool Field_enum::can_optimize_keypart_ref(const Item_bool_func *cond,
const Item *item) const
{
- DBUG_ASSERT(cmp_type() == INT_RESULT);
- DBUG_ASSERT(result_type() == STRING_RESULT);
-
switch (item->cmp_type())
{
case TIME_RESULT:
@@ -9161,7 +9053,8 @@ bool Field_enum::can_optimize_keypart_ref(const Item_bool_func *cond,
Field_bit::Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
- enum utype unireg_check_arg, const char *field_name_arg)
+ enum utype unireg_check_arg,
+ const LEX_CSTRING *field_name_arg)
: Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg),
bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7),
@@ -9245,8 +9138,8 @@ Field *Field_bit::new_key_field(MEM_ROOT *root, TABLE *new_table,
uint Field_bit::is_equal(Create_field *new_field)
{
- return (new_field->sql_type == real_type() &&
- new_field->length == max_display_length());
+ return new_field->type_handler() == type_handler() &&
+ new_field->length == max_display_length();
}
@@ -9676,7 +9569,7 @@ void Field_bit::set_default()
Field_bit_as_char::Field_bit_as_char(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, 0, 0,
unireg_check_arg, field_name_arg)
{
@@ -9727,59 +9620,192 @@ void Field_bit_as_char::sql_type(String &res) const
Handling of field and Create_field
*****************************************************************************/
-/**
- Convert create_field::length from number of characters to number of bytes.
-*/
-
-void Column_definition::create_length_to_internal_length(void)
-{
- switch (sql_type) {
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_GEOMETRY:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VARCHAR:
- length*= charset->mbmaxlen;
- key_length= length;
- pack_length= calc_pack_length(sql_type, length);
- break;
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- /* Pack_length already calculated in sql_parse.cc */
- length*= charset->mbmaxlen;
- key_length= pack_length;
- break;
- case MYSQL_TYPE_BIT:
- if (f_bit_as_char(pack_flag))
+bool Column_definition::create_interval_from_interval_list(MEM_ROOT *mem_root,
+ bool reuse_interval_list_values)
+{
+ DBUG_ENTER("Column_definition::create_interval_from_interval_list");
+ DBUG_ASSERT(!interval);
+ if (!(interval= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB))))
+ DBUG_RETURN(true); // EOM
+
+ List_iterator<String> it(interval_list);
+ StringBuffer<64> conv;
+ char comma_buf[5]; /* 5 bytes for 'filename' charset */
+ DBUG_ASSERT(sizeof(comma_buf) >= charset->mbmaxlen);
+ int comma_length= charset->cset->wc_mb(charset, ',',
+ (uchar*) comma_buf,
+ (uchar*) comma_buf +
+ sizeof(comma_buf));
+ DBUG_ASSERT(comma_length >= 0 && comma_length <= (int) sizeof(comma_buf));
+
+ if (!multi_alloc_root(mem_root,
+ &interval->type_names,
+ sizeof(char*) * (interval_list.elements + 1),
+ &interval->type_lengths,
+ sizeof(uint) * (interval_list.elements + 1),
+ NullS))
+ goto err; // EOM
+
+ interval->name= "";
+ interval->count= interval_list.elements;
+
+ for (uint i= 0; i < interval->count; i++)
+ {
+ uint32 dummy;
+ String *tmp= it++;
+ LEX_CSTRING value;
+ if (String::needs_conversion(tmp->length(), tmp->charset(),
+ charset, &dummy))
{
- key_length= pack_length= ((length + 7) & ~7) / 8;
+ uint cnv_errs;
+ conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), charset, &cnv_errs);
+ value.str= strmake_root(mem_root, conv.ptr(), conv.length());
+ value.length= conv.length();
}
else
{
- pack_length= length / 8;
- /* We need one extra byte to store the bits we save among the null bits */
- key_length= pack_length + MY_TEST(length & 7);
+ value.str= reuse_interval_list_values ? tmp->ptr() :
+ strmake_root(mem_root,
+ tmp->ptr(),
+ tmp->length());
+ value.length= tmp->length();
}
- break;
- case MYSQL_TYPE_NEWDECIMAL:
- key_length= pack_length=
- my_decimal_get_binary_size(my_decimal_length_to_precision(length,
- decimals,
- flags &
- UNSIGNED_FLAG),
- decimals);
- break;
- default:
- key_length= pack_length= calc_pack_length(sql_type, length);
- break;
+ if (!value.str)
+ goto err; // EOM
+
+ // Strip trailing spaces.
+ value.length= charset->cset->lengthsp(charset, value.str, value.length);
+ ((char*) value.str)[value.length]= '\0';
+
+ if (real_field_type() == MYSQL_TYPE_SET)
+ {
+ if (charset->coll->instr(charset, value.str, value.length,
+ comma_buf, comma_length, NULL, 0))
+ {
+ ErrConvString err(tmp);
+ my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", err.ptr());
+ goto err;
+ }
+ }
+ interval->type_names[i]= value.str;
+ interval->type_lengths[i]= value.length;
+ }
+ interval->type_names[interval->count]= 0; // End marker
+ interval->type_lengths[interval->count]= 0;
+ interval_list.empty(); // Don't need interval_list anymore
+ DBUG_RETURN(false);
+err:
+ interval= NULL; // Avoid having both non-empty interval_list and interval
+ DBUG_RETURN(true);
+}
+
+
+bool Column_definition::prepare_interval_field(MEM_ROOT *mem_root,
+ bool reuse_interval_list_values)
+{
+ DBUG_ENTER("Column_definition::prepare_interval_field");
+ DBUG_ASSERT(real_field_type() == MYSQL_TYPE_ENUM ||
+ real_field_type() == MYSQL_TYPE_SET);
+ /*
+ Interval values are either in "interval" or in "interval_list",
+ but not in both at the same time, and are not empty at the same time.
+ - Values are in "interval_list" when we're coming from the parser
+ in CREATE TABLE or in CREATE {FUNCTION|PROCEDURE}.
+ - Values are in "interval" when we're in ALTER TABLE.
+
+ In a corner case with an empty set like SET(''):
+ - after the parser we have interval_list.elements==1
+ - in ALTER TABLE we have a non-NULL interval with interval->count==1,
+ with interval->type_names[0]=="" and interval->type_lengths[0]==0.
+ So the assert is still valid for this corner case.
+
+ ENUM and SET with no values at all (e.g. ENUM(), SET()) are not possible,
+ as the parser requires at least one element, so for a ENUM or SET field it
+ should never happen that both internal_list.elements and interval are 0.
+ */
+ DBUG_ASSERT((interval == NULL) == (interval_list.elements > 0));
+
+ /*
+ Create typelib from interval_list, and if necessary
+ convert strings from client character set to the
+ column character set.
+ */
+ if (interval_list.elements &&
+ create_interval_from_interval_list(mem_root,
+ reuse_interval_list_values))
+ DBUG_RETURN(true);
+
+ if (!reuse_interval_list_values)
+ {
+ /*
+ We're initializing from an existing table or view Field_enum
+ (e.g. for a %TYPE variable) rather than from the parser.
+ The constructor Column_definition(THD*,Field*,Field*) has already
+ copied the TYPELIB pointer from the original Field_enum.
+ Now we need to make a permanent copy of that TYPELIB,
+ as the original field can be freed before the end of the life
+ cycle of "this".
+ */
+ DBUG_ASSERT(interval);
+ if (!(interval= copy_typelib(mem_root, interval)))
+ DBUG_RETURN(true);
+ }
+ prepare_interval_field_calc_length();
+ DBUG_RETURN(false);
+}
+
+
+void Column_definition::set_attributes(const Lex_field_type_st &type,
+ CHARSET_INFO *cs)
+{
+ DBUG_ASSERT(type_handler() == &type_handler_null);
+ DBUG_ASSERT(charset == &my_charset_bin || charset == NULL);
+ DBUG_ASSERT(length == 0);
+ DBUG_ASSERT(decimals == 0);
+
+ set_handler(type.type_handler());
+ charset= cs;
+
+ if (type.length())
+ {
+ int err;
+ length= my_strtoll10(type.length(), NULL, &err);
+ if (err)
+ length= ~0ULL; // safety
+ }
+
+ if (type.dec())
+ decimals= (uint) atoi(type.dec());
+}
+
+
+void Column_definition::create_length_to_internal_length_bit()
+{
+ if (f_bit_as_char(pack_flag))
+ {
+ key_length= pack_length= ((length + 7) & ~7) / 8;
+ }
+ else
+ {
+ pack_length= length / 8;
+ /* We need one extra byte to store the bits we save among the null bits */
+ key_length= pack_length + MY_TEST(length & 7);
}
}
-bool check_expression(Virtual_column_info *vcol, const char *name,
+void Column_definition::create_length_to_internal_length_newdecimal()
+{
+ key_length= pack_length=
+ my_decimal_get_binary_size(my_decimal_length_to_precision(length,
+ decimals,
+ flags &
+ UNSIGNED_FLAG),
+ decimals);
+}
+
+
+bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
enum_vcol_info_type type)
{
@@ -9787,7 +9813,7 @@ bool check_expression(Virtual_column_info *vcol, const char *name,
Item::vcol_func_processor_result res;
if (!vcol->name.length)
- vcol->name.str= const_cast<char*>(name);
+ vcol->name= *name;
/*
Walk through the Item tree checking if all items are valid
@@ -9804,7 +9830,7 @@ bool check_expression(Virtual_column_info *vcol, const char *name,
if (ret || (res.errors & filter))
{
my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), res.name,
- vcol_type_name(type), name);
+ vcol_type_name(type), name->str);
return TRUE;
}
/*
@@ -9817,31 +9843,118 @@ bool check_expression(Virtual_column_info *vcol, const char *name,
}
+bool Column_definition::check_length(uint mysql_errno, uint limit) const
+{
+ if (length <= limit)
+ return false;
+ my_error(mysql_errno, MYF(0), field_name.str, static_cast<ulong>(limit));
+ return true;
+}
+
+
+bool Column_definition::fix_attributes_int(uint default_length)
+{
+ if (length)
+ return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_CHARLENGTH);
+ length= default_length;
+ return false;
+}
+
+
+bool Column_definition::fix_attributes_real(uint default_length)
+{
+ /* change FLOAT(precision) to FLOAT or DOUBLE */
+ if (!length && !decimals)
+ {
+ length= default_length;
+ decimals= NOT_FIXED_DEC;
+ }
+ if (length < decimals && decimals != NOT_FIXED_DEC)
+ {
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
+ return true;
+ }
+ if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
+ field_name.str, static_cast<uint>(FLOATING_POINT_DECIMALS-1));
+ return true;
+ }
+ return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_CHARLENGTH);
+}
+
+
+bool Column_definition::fix_attributes_decimal()
+{
+ if (decimals >= NOT_FIXED_DEC)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
+ field_name.str, static_cast<uint>(NOT_FIXED_DEC - 1));
+ return true;
+ }
+ my_decimal_trim(&length, &decimals);
+ if (length > DECIMAL_MAX_PRECISION)
+ {
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
+ DECIMAL_MAX_PRECISION);
+ return true;
+ }
+ if (length < decimals)
+ {
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name.str);
+ return true;
+ }
+ length= my_decimal_precision_to_length(length, decimals,
+ flags & UNSIGNED_FLAG);
+ pack_length= my_decimal_get_binary_size(length, decimals);
+ return false;
+}
+
+
+bool Column_definition::fix_attributes_bit()
+{
+ if (!length)
+ length= 1;
+ pack_length= (length + 7) / 8;
+ return check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_BIT_FIELD_LENGTH);
+}
+
+
+bool Column_definition::fix_attributes_temporal_with_time(uint int_part_length)
+{
+ if (length > MAX_DATETIME_PRECISION)
+ {
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name.str,
+ MAX_DATETIME_PRECISION);
+ return true;
+ }
+ length+= int_part_length + (length ? 1 : 0);
+ return false;
+}
+
+
bool Column_definition::check(THD *thd)
{
- const uint conditional_type_modifiers= AUTO_INCREMENT_FLAG;
- uint sign_len, allowed_type_modifier= 0;
- ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("Column_definition::check");
/* Initialize data for a computed field */
if (vcol_info)
{
DBUG_ASSERT(vcol_info->expr);
- vcol_info->set_field_type(sql_type);
- if (check_expression(vcol_info, field_name, vcol_info->stored_in_db
+ vcol_info->set_field_type(real_field_type());
+ if (check_expression(vcol_info, &field_name, vcol_info->stored_in_db
? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL))
DBUG_RETURN(TRUE);
}
if (check_constraint &&
- check_expression(check_constraint, field_name, VCOL_CHECK_FIELD))
+ check_expression(check_constraint, &field_name, VCOL_CHECK_FIELD))
DBUG_RETURN(1);
if (default_value)
{
Item *def_expr= default_value->expr;
- if (check_expression(default_value, field_name, VCOL_DEFAULT))
+ if (check_expression(default_value, &field_name, VCOL_DEFAULT))
DBUG_RETURN(TRUE);
/* Constant's are stored in the 'empty_record', except for blobs */
@@ -9852,7 +9965,7 @@ bool Column_definition::check(THD *thd)
default_value= 0;
if ((flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG)
{
- my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
DBUG_RETURN(1);
}
}
@@ -9861,12 +9974,12 @@ bool Column_definition::check(THD *thd)
if (default_value && (flags & AUTO_INCREMENT_FLAG))
{
- my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
DBUG_RETURN(1);
}
if (default_value && !default_value->expr->basic_const_item() &&
- mysql_type_to_time_type(sql_type) == MYSQL_TIMESTAMP_DATETIME &&
+ mysql_timestamp_type() == MYSQL_TIMESTAMP_DATETIME &&
default_value->expr->type() == Item::FUNC_ITEM)
{
/*
@@ -9884,10 +9997,10 @@ bool Column_definition::check(THD *thd)
if (on_update)
{
- if (mysql_type_to_time_type(sql_type) != MYSQL_TIMESTAMP_DATETIME ||
+ if (mysql_timestamp_type() != MYSQL_TIMESTAMP_DATETIME ||
on_update->decimals < length)
{
- my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
+ my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name.str);
DBUG_RETURN(TRUE);
}
unireg_check= unireg_check == Field::NONE ? Field::TIMESTAMP_UN_FIELD
@@ -9896,186 +10009,9 @@ bool Column_definition::check(THD *thd)
else if (flags & AUTO_INCREMENT_FLAG)
unireg_check= Field::NEXT_NUMBER;
- sign_len= flags & UNSIGNED_FLAG ? 0 : 1;
+ if (type_handler()->Column_definition_fix_attributes(this))
+ DBUG_RETURN(true);
- switch (sql_type) {
- case MYSQL_TYPE_TINY:
- if (!length)
- length= MAX_TINYINT_WIDTH+sign_len;
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- break;
- case MYSQL_TYPE_SHORT:
- if (!length)
- length= MAX_SMALLINT_WIDTH+sign_len;
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- break;
- case MYSQL_TYPE_INT24:
- if (!length)
- length= MAX_MEDIUMINT_WIDTH+sign_len;
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- break;
- case MYSQL_TYPE_LONG:
- if (!length)
- length= MAX_INT_WIDTH+sign_len;
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- break;
- case MYSQL_TYPE_LONGLONG:
- if (!length)
- length= MAX_BIGINT_WIDTH;
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- break;
- case MYSQL_TYPE_NULL:
- break;
- case MYSQL_TYPE_NEWDECIMAL:
- if (decimals >= NOT_FIXED_DEC)
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
- field_name, static_cast<ulong>(NOT_FIXED_DEC - 1));
- DBUG_RETURN(TRUE);
- }
- my_decimal_trim(&length, &decimals);
- if (length > DECIMAL_MAX_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
- DECIMAL_MAX_PRECISION);
- DBUG_RETURN(TRUE);
- }
- if (length < decimals)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
- DBUG_RETURN(TRUE);
- }
- length=
- my_decimal_precision_to_length(length, decimals, flags & UNSIGNED_FLAG);
- pack_length=
- my_decimal_get_binary_size(length, decimals);
- break;
- case MYSQL_TYPE_VARCHAR:
- /*
- Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
- if they don't have a default value
- */
- max_field_charlength= MAX_FIELD_VARCHARLENGTH;
- break;
- case MYSQL_TYPE_STRING:
- break;
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_GEOMETRY:
- flags|= BLOB_FLAG;
- break;
- case MYSQL_TYPE_YEAR:
- if (!length || length != 2)
- length= 4; /* Default length */
- flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
- break;
- case MYSQL_TYPE_FLOAT:
- /* change FLOAT(precision) to FLOAT or DOUBLE */
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- if (!length && !decimals)
- {
- length= MAX_FLOAT_STR_LENGTH;
- decimals= NOT_FIXED_DEC;
- }
- if (length < decimals &&
- decimals != NOT_FIXED_DEC)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
- DBUG_RETURN(TRUE);
- }
- if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS)
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
- field_name, static_cast<ulong>(FLOATING_POINT_DECIMALS-1));
- DBUG_RETURN(TRUE);
- }
- break;
- case MYSQL_TYPE_DOUBLE:
- allowed_type_modifier= AUTO_INCREMENT_FLAG;
- if (!length && !decimals)
- {
- length= DBL_DIG+7;
- decimals= NOT_FIXED_DEC;
- }
- if (length < decimals &&
- decimals != NOT_FIXED_DEC)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
- DBUG_RETURN(TRUE);
- }
- if (decimals != NOT_FIXED_DEC && decimals >= FLOATING_POINT_DECIMALS)
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), static_cast<ulonglong>(decimals),
- field_name, static_cast<ulong>(FLOATING_POINT_DECIMALS-1));
- DBUG_RETURN(TRUE);
- }
- break;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_TIMESTAMP2:
- if (length > MAX_DATETIME_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
- MAX_DATETIME_PRECISION);
- DBUG_RETURN(TRUE);
- }
- length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
- flags|= UNSIGNED_FLAG;
- break;
- case MYSQL_TYPE_DATE:
- /* We don't support creation of MYSQL_TYPE_DATE anymore */
- sql_type= MYSQL_TYPE_NEWDATE;
- /* fall through */
- case MYSQL_TYPE_NEWDATE:
- length= MAX_DATE_WIDTH;
- break;
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_TIME2:
- if (length > MAX_DATETIME_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
- MAX_DATETIME_PRECISION);
- DBUG_RETURN(TRUE);
- }
- length+= MIN_TIME_WIDTH + (length ? 1 : 0);
- break;
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_DATETIME2:
- if (length > MAX_DATETIME_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
- MAX_DATETIME_PRECISION);
- DBUG_RETURN(TRUE);
- }
- length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
- break;
- case MYSQL_TYPE_SET:
- pack_length= get_set_pack_length(interval_list.elements);
- break;
- case MYSQL_TYPE_ENUM:
- /* Should be safe. */
- pack_length= get_enum_pack_length(interval_list.elements);
- break;
- case MYSQL_TYPE_VAR_STRING:
- DBUG_ASSERT(0); /* Impossible. */
- break;
- case MYSQL_TYPE_BIT:
- {
- if (!length)
- length= 1;
- if (length > MAX_BIT_FIELD_LENGTH)
- {
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name,
- static_cast<ulong>(MAX_BIT_FIELD_LENGTH));
- DBUG_RETURN(TRUE);
- }
- pack_length= (length + 7) / 8;
- break;
- }
- case MYSQL_TYPE_DECIMAL:
- DBUG_ASSERT(0); /* Was obsolete */
- }
/* Remember the value of length */
char_length= length;
@@ -10092,37 +10028,17 @@ bool Column_definition::check(THD *thd)
explicit_defaults_for_timestamp is not set.
*/
if (opt_explicit_defaults_for_timestamp ||
- !is_timestamp_type(sql_type))
+ !is_timestamp_type())
{
flags|= NO_DEFAULT_VALUE_FLAG;
}
}
- if (!(flags & BLOB_FLAG) &&
- ((length > max_field_charlength &&
- sql_type != MYSQL_TYPE_VARCHAR) ||
- (length == 0 &&
- sql_type != MYSQL_TYPE_ENUM && sql_type != MYSQL_TYPE_SET &&
- sql_type != MYSQL_TYPE_STRING && sql_type != MYSQL_TYPE_VARCHAR &&
- sql_type != MYSQL_TYPE_GEOMETRY)))
- {
- my_error((sql_type == MYSQL_TYPE_VAR_STRING ||
- sql_type == MYSQL_TYPE_VARCHAR ||
- sql_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
- ER_TOO_BIG_DISPLAYWIDTH,
- MYF(0),
- field_name, max_field_charlength); /* purecov: inspected */
- DBUG_RETURN(TRUE);
- }
- else if (length > MAX_FIELD_BLOBLENGTH)
- {
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH);
- DBUG_RETURN(1);
- }
- if ((~allowed_type_modifier) & flags & conditional_type_modifiers)
+ if ((flags & AUTO_INCREMENT_FLAG) &&
+ !type_handler()->type_can_have_auto_increment_attribute())
{
- my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name.str);
DBUG_RETURN(TRUE);
}
@@ -10144,64 +10060,6 @@ enum_field_types get_blob_type_from_length(ulong length)
}
-/*
- Make a field from the .frm file info
-*/
-
-uint32 calc_pack_length(enum_field_types type,uint32 length)
-{
- switch (type) {
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_DECIMAL: return (length);
- case MYSQL_TYPE_VARCHAR: return (length + (length < 256 ? 1: 2));
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_TINY : return 1;
- case MYSQL_TYPE_SHORT : return 2;
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_NEWDATE: return 3;
- case MYSQL_TYPE_TIME: return length > MIN_TIME_WIDTH
- ? time_hires_bytes[length - 1 - MIN_TIME_WIDTH]
- : 3;
- case MYSQL_TYPE_TIME2:
- return length > MIN_TIME_WIDTH ?
- my_time_binary_length(length - MIN_TIME_WIDTH - 1) : 3;
- case MYSQL_TYPE_TIMESTAMP:
- return length > MAX_DATETIME_WIDTH
- ? 4 + sec_part_bytes[length - 1 - MAX_DATETIME_WIDTH]
- : 4;
- case MYSQL_TYPE_TIMESTAMP2:
- return length > MAX_DATETIME_WIDTH ?
- my_timestamp_binary_length(length - MAX_DATETIME_WIDTH - 1) : 4;
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_LONG : return 4;
- case MYSQL_TYPE_FLOAT : return sizeof(float);
- case MYSQL_TYPE_DOUBLE: return sizeof(double);
- case MYSQL_TYPE_DATETIME:
- return length > MAX_DATETIME_WIDTH
- ? datetime_hires_bytes[length - 1 - MAX_DATETIME_WIDTH]
- : 8;
- case MYSQL_TYPE_DATETIME2:
- return length > MAX_DATETIME_WIDTH ?
- my_datetime_binary_length(length - MAX_DATETIME_WIDTH - 1) : 5;
- case MYSQL_TYPE_LONGLONG: return 8; /* Don't crash if no longlong */
- case MYSQL_TYPE_NULL : return 0;
- case MYSQL_TYPE_TINY_BLOB: return 1+portable_sizeof_char_ptr;
- case MYSQL_TYPE_BLOB: return 2+portable_sizeof_char_ptr;
- case MYSQL_TYPE_MEDIUM_BLOB: return 3+portable_sizeof_char_ptr;
- case MYSQL_TYPE_LONG_BLOB: return 4+portable_sizeof_char_ptr;
- case MYSQL_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr;
- case MYSQL_TYPE_SET:
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_NEWDECIMAL:
- abort(); return 0; // This shouldn't happen
- case MYSQL_TYPE_BIT: return length / 8;
- default:
- return 0;
- }
-}
-
-
uint pack_length_to_packflag(uint type)
{
switch (type) {
@@ -10220,17 +10078,17 @@ Field *make_field(TABLE_SHARE *share,
uchar *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
uint pack_flag,
- enum_field_types field_type,
+ const Type_handler *handler,
CHARSET_INFO *field_charset,
Field::geometry_type geom_type, uint srid,
Field::utype unireg_check,
TYPELIB *interval,
- const char *field_name)
+ const LEX_CSTRING *field_name)
{
uchar *UNINIT_VAR(bit_ptr);
uchar UNINIT_VAR(bit_offset);
- if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
+ if (handler->real_field_type() == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
{
bit_ptr= null_pos;
bit_offset= null_bit;
@@ -10251,8 +10109,8 @@ Field *make_field(TABLE_SHARE *share,
null_bit= ((uchar) 1) << null_bit;
}
- DBUG_PRINT("debug", ("field_type: %d, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
- field_type, field_length, interval,
+ DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
+ handler->name().ptr(), field_length, interval,
FLAGSTR(pack_flag, FIELDFLAG_BINARY),
FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
@@ -10263,6 +10121,7 @@ Field *make_field(TABLE_SHARE *share,
{
if (!f_is_packed(pack_flag))
{
+ enum_field_types field_type= handler->real_field_type();
if (field_type == MYSQL_TYPE_STRING ||
field_type == MYSQL_TYPE_DECIMAL || // 3.23 or 4.0 string
field_type == MYSQL_TYPE_VAR_STRING)
@@ -10281,9 +10140,12 @@ Field *make_field(TABLE_SHARE *share,
return 0; // Error
}
- uint pack_length=calc_pack_length((enum_field_types)
- f_packtype(pack_flag),
- field_length);
+ // MYSQL_TYPE_VAR_STRING is handled above
+ DBUG_ASSERT(f_packtype(pack_flag) != MYSQL_TYPE_VAR_STRING);
+ const Type_handler *tmp;
+ tmp= Type_handler::get_handler_by_real_type((enum_field_types)
+ f_packtype(pack_flag));
+ uint pack_length= tmp->calc_pack_length(field_length);
#ifdef HAVE_SPATIAL
if (f_is_geom(pack_flag))
@@ -10315,7 +10177,7 @@ Field *make_field(TABLE_SHARE *share,
}
}
- switch (field_type) {
+ switch (handler->real_field_type()) {
case MYSQL_TYPE_DECIMAL:
return new (mem_root)
Field_decimal(ptr,field_length,null_pos,null_bit,
@@ -10466,13 +10328,14 @@ Field *make_field(TABLE_SHARE *share,
Column_definition::Column_definition(THD *thd, Field *old_field,
Field *orig_field)
{
+ on_update= NULL;
field_name= old_field->field_name;
length= old_field->field_length;
flags= old_field->flags;
unireg_check=old_field->unireg_check;
pack_length=old_field->pack_length();
key_length= old_field->key_length();
- sql_type= old_field->real_type();
+ set_handler(old_field->type_handler());
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
@@ -10480,22 +10343,20 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
default_value= orig_field ? orig_field->default_value : 0;
check_constraint= orig_field ? orig_field->check_constraint : 0;
option_list= old_field->option_list;
+ pack_flag= 0;
- switch (sql_type) {
+ switch (real_field_type()) {
+ case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_BLOB:
- switch (pack_length - portable_sizeof_char_ptr) {
- case 1: sql_type= MYSQL_TYPE_TINY_BLOB; break;
- case 2: sql_type= MYSQL_TYPE_BLOB; break;
- case 3: sql_type= MYSQL_TYPE_MEDIUM_BLOB; break;
- default: sql_type= MYSQL_TYPE_LONG_BLOB; break;
- }
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
length/= charset->mbmaxlen;
key_length/= charset->mbmaxlen;
break;
case MYSQL_TYPE_STRING:
/* Change CHAR -> VARCHAR if dynamic record length */
if (old_field->type() == MYSQL_TYPE_VAR_STRING)
- sql_type= MYSQL_TYPE_VARCHAR;
+ set_handler(&type_handler_varchar);
/* fall through */
case MYSQL_TYPE_ENUM:
@@ -10539,6 +10400,9 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
interval= ((Field_enum*) old_field)->typelib;
else
interval=0;
+
+ interval_list.empty(); // prepare_interval_field() needs this
+
char_length= length;
/*
@@ -10578,6 +10442,33 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
/**
+ The common part for data type redefinition:
+ CREATE TABLE t1 (a INT) AS SELECT a FROM t2;
+ See Type_handler::Column_definition_redefine_stage1()
+ for data type specific code.
+*/
+void
+Column_definition::redefine_stage1_common(const Column_definition *dup_field,
+ const handler *file,
+ const Schema_specification_st *schema)
+{
+ set_handler(dup_field->type_handler());
+ default_value= dup_field->default_value;
+ charset= dup_field->charset ? dup_field->charset :
+ schema->default_table_charset;
+ length= dup_field->char_length;
+ pack_length= dup_field->pack_length;
+ key_length= dup_field->key_length;
+ decimals= dup_field->decimals;
+ unireg_check= dup_field->unireg_check;
+ flags= dup_field->flags;
+ interval= dup_field->interval;
+ vcol_info= dup_field->vcol_info;
+}
+
+
+
+/**
maximum possible character length for blob.
This method is used in Item_field::set_field to calculate
@@ -10602,7 +10493,7 @@ uint32 Field_blob::char_length() const
case 3:
return 16777215;
case 4:
- return (uint32) 4294967295U;
+ return (uint32) UINT_MAX32;
default:
DBUG_ASSERT(0); // we should never go here
return 0;
@@ -10655,7 +10546,7 @@ uint32 Field_blob::max_display_length()
case 3:
return 16777215 * field_charset->mbmaxlen;
case 4:
- return (uint32) 4294967295U;
+ return (uint32) UINT_MAX32;
default:
DBUG_ASSERT(0); // we should never go here
return 0;
@@ -10699,7 +10590,7 @@ Field::set_warning(Sql_condition::enum_warning_level level, uint code,
if (thd->count_cuted_fields)
{
thd->cuted_fields+= cut_increment;
- push_warning_printf(thd, level, code, ER_THD(thd, code), field_name,
+ push_warning_printf(thd, level, code, ER_THD(thd, code), field_name.str,
thd->get_stmt_da()->current_row_for_warning());
return 0;
}
@@ -10732,7 +10623,7 @@ void Field::set_datetime_warning(Sql_condition::enum_warning_level level,
{
THD *thd= get_thd();
if (thd->really_abort_on_warning() && level >= Sql_condition::WARN_LEVEL_WARN)
- make_truncated_value_warning(thd, level, str, ts_type, field_name);
+ make_truncated_value_warning(thd, level, str, ts_type, field_name.str);
else
set_warning(level, code, cuted_increment);
}
@@ -10745,7 +10636,7 @@ void Field::set_warning_truncated_wrong_value(const char *type_arg,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
- type_arg, value, field_name,
+ type_arg, value, field_name.str,
static_cast<ulong>(thd->get_stmt_da()->
current_row_for_warning()));
}
@@ -10814,7 +10705,7 @@ bool Field::validate_value_in_record_with_warn(THD *thd, const uchar *record)
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_INVALID_DEFAULT_VALUE_FOR_FIELD,
ER_THD(thd, ER_INVALID_DEFAULT_VALUE_FOR_FIELD),
- ErrConvString(&tmp).ptr(), field_name);
+ ErrConvString(&tmp).ptr(), field_name.str);
}
dbug_tmp_restore_column_map(table->read_set, old_map);
return rc;
@@ -10849,7 +10740,7 @@ bool Field::save_in_field_default_value(bool view_error_processing)
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_FIELD,
ER_THD(thd, ER_NO_DEFAULT_FOR_FIELD),
- field_name);
+ field_name.str);
}
return 1;
}
diff --git a/sql/field.h b/sql/field.h
index 18d66ed8891..208941b3daa 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -31,6 +31,7 @@
#include "my_decimal.h" /* my_decimal */
#include "sql_error.h" /* Sql_condition */
#include "compat56.h"
+#include "sql_type.h" /* Type_std_attributes */
class Send_field;
class Copy_field;
@@ -364,24 +365,25 @@ public:
Subst_constraint m_subst_constraint;
/*
Comparison type.
- Impostant only when ANY_SUBSTS.
+ Important only when ANY_SUBSTS.
*/
- Item_result m_compare_type;
+ const Type_handler *m_compare_handler;
/*
Collation of the comparison operation.
Important only when ANY_SUBST.
*/
CHARSET_INFO *m_compare_collation;
public:
- Context(Subst_constraint subst, Item_result type, CHARSET_INFO *cs)
+ Context(Subst_constraint subst, const Type_handler *h, CHARSET_INFO *cs)
:m_subst_constraint(subst),
- m_compare_type(type),
- m_compare_collation(cs) { }
+ m_compare_handler(h),
+ m_compare_collation(cs)
+ { DBUG_ASSERT(h == h->type_handler_for_comparison()); }
Subst_constraint subst_constraint() const { return m_subst_constraint; }
- Item_result compare_type() const
+ const Type_handler *compare_type_handler() const
{
DBUG_ASSERT(m_subst_constraint == ANY_SUBST);
- return m_compare_type;
+ return m_compare_handler;
}
CHARSET_INFO *compare_collation() const
{
@@ -393,35 +395,21 @@ public:
{ // Use this to request only exact value, no invariants.
public:
Context_identity()
- :Context(IDENTITY_SUBST, STRING_RESULT, &my_charset_bin) { }
+ :Context(IDENTITY_SUBST, &type_handler_long_blob, &my_charset_bin) { }
};
class Context_boolean: public Context
{ // Use this when an item is [a part of] a boolean expression
public:
- Context_boolean() :Context(ANY_SUBST, INT_RESULT, &my_charset_bin) { }
+ Context_boolean()
+ :Context(ANY_SUBST, &type_handler_longlong, &my_charset_bin) { }
};
};
-enum Derivation
-{
- DERIVATION_IGNORABLE= 6,
- DERIVATION_NUMERIC= 5,
- DERIVATION_COERCIBLE= 4,
- DERIVATION_SYSCONST= 3,
- DERIVATION_IMPLICIT= 2,
- DERIVATION_NONE= 1,
- DERIVATION_EXPLICIT= 0
-};
-
-
#define STORAGE_TYPE_MASK 7
#define COLUMN_FORMAT_MASK 7
#define COLUMN_FORMAT_SHIFT 3
-#define my_charset_numeric my_charset_latin1
-#define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII
-
/* The length of the header part for each virtual column in the .frm file */
#define FRM_VCOL_OLD_HEADER_SIZE(b) (3 + MY_TEST(b))
#define FRM_VCOL_NEW_BASE_SIZE 16
@@ -474,16 +462,6 @@ inline bool is_temporal_type_with_date(enum_field_types type)
/**
- Recognizer for concrete data type (called real_type for some reason),
- returning true if it is one of the TIMESTAMP types.
-*/
-inline bool is_timestamp_type(enum_field_types type)
-{
- return type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_TIMESTAMP2;
-}
-
-
-/**
Convert temporal real types as retuned by field->real_type()
to field type as returned by field->type().
@@ -539,27 +517,6 @@ inline bool is_temporal_type(enum_field_types type)
}
-/**
- Tests if field type is temporal and has time part,
- i.e. represents TIME, DATETIME or TIMESTAMP types in SQL.
-
- @param type Field type, as returned by field->type().
- @retval true If field type is temporal type with time part.
- @retval false If field type is not temporal type with time part.
-*/
-inline bool is_temporal_type_with_time(enum_field_types type)
-{
- switch (type)
- {
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- return true;
- default:
- return false;
- }
-}
-
enum enum_vcol_info_type
{
VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED,
@@ -629,7 +586,7 @@ public:
bool stored_in_db;
bool utf8; /* Already in utf8 */
Item *expr;
- LEX_STRING name; /* Name of constraint */
+ LEX_CSTRING name; /* Name of constraint */
uint flags;
Virtual_column_info()
@@ -721,12 +678,12 @@ public:
*/
TABLE *table; // Pointer for table
TABLE *orig_table; // Pointer to original table
- const char * const *table_name;
- const char *field_name;
+ const char * const *table_name; // Pointer to alias in TABLE
+ LEX_CSTRING field_name;
+ LEX_CSTRING comment;
/** reference to the list of options or NULL */
engine_option_value *option_list;
ha_field_option_struct *option_struct; /* structure with parsed options */
- LEX_STRING comment;
/* Field is part of the following keys */
key_map key_start, part_of_key, part_of_key_not_clustered;
@@ -815,8 +772,20 @@ public:
Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg);
+ const LEX_CSTRING *field_name_arg);
virtual ~Field() {}
+
+ DTCollation dtcollation() const
+ {
+ return DTCollation(charset(), derivation(), repertoire());
+ }
+ Type_std_attributes type_std_attributes() const
+ {
+ return Type_std_attributes(field_length, decimals(),
+ MY_TEST(flags & UNSIGNED_FLAG),
+ dtcollation());
+ }
+
/**
Convenience definition of a copy function returned by
Field::get_copy_func()
@@ -847,6 +816,10 @@ public:
enum_check_fields check_level);
int store(const LEX_STRING *ls, CHARSET_INFO *cs)
{ return store(ls->str, ls->length, cs); }
+ int store(const LEX_CSTRING *ls, CHARSET_INFO *cs)
+ { return store(ls->str, ls->length, cs); }
+ int store(const LEX_CSTRING &ls, CHARSET_INFO *cs)
+ { return store(ls.str, ls.length, cs); }
virtual double val_real(void)=0;
virtual longlong val_int(void)=0;
virtual bool val_bool(void)= 0;
@@ -872,11 +845,15 @@ public:
to be quoted when used in constructing an SQL query.
*/
virtual bool str_needs_quotes() { return FALSE; }
- virtual Item_result result_type () const=0;
- virtual Item_result cmp_type () const { return result_type(); }
- static bool type_can_have_key_part(enum_field_types);
+ Item_result result_type () const
+ {
+ return type_handler()->result_type();
+ }
+ Item_result cmp_type () const
+ {
+ return type_handler()->cmp_type();
+ }
static enum_field_types field_type_merge(enum_field_types, enum_field_types);
- static Item_result result_merge_type(enum_field_types);
virtual bool eq(Field *field)
{
return (ptr == field->ptr && null_ptr == field->null_ptr &&
@@ -989,8 +966,15 @@ public:
virtual bool zero_pack() const { return 1; }
virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
virtual uint32 key_length() const { return pack_length(); }
- virtual enum_field_types type() const =0;
- virtual enum_field_types real_type() const { return type(); }
+ virtual const Type_handler *type_handler() const= 0;
+ virtual enum_field_types type() const
+ {
+ return type_handler()->field_type();
+ }
+ virtual enum_field_types real_type() const
+ {
+ return type_handler()->real_field_type();
+ }
virtual enum_field_types binlog_type() const
{
/*
@@ -1307,6 +1291,7 @@ public:
uint fill_cache_field(struct st_cache_field *copy);
virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_time(MYSQL_TIME *ltime) { return get_date(ltime, TIME_TIME_ONLY); }
+ virtual TYPELIB *get_typelib() const { return NULL; }
virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; }
virtual CHARSET_INFO *charset_for_protocol(void) const
{ return binary() ? &my_charset_bin : charset(); }
@@ -1315,9 +1300,6 @@ public:
virtual enum Derivation derivation(void) const
{ return DERIVATION_IMPLICIT; }
virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
- virtual void set_derivation(enum Derivation derivation_arg,
- uint repertoire_arg)
- { }
virtual int set_time() { return 1; }
bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
int cuted_increment) const;
@@ -1330,7 +1312,7 @@ protected:
{
return set_warning(Sql_condition::WARN_LEVEL_NOTE, code, cuted_increment);
}
- void set_datetime_warning(Sql_condition::enum_warning_level, uint code,
+ void set_datetime_warning(Sql_condition::enum_warning_level, uint code,
const ErrConv *str, timestamp_type ts_type,
int cuted_increment) const;
void set_datetime_warning(uint code,
@@ -1546,7 +1528,7 @@ protected:
return to + size;
}
- const uchar *unpack_int(uchar* to, const uchar *from,
+ const uchar *unpack_int(uchar* to, const uchar *from,
const uchar *from_end, size_t size)
{
if (from + size > from_end)
@@ -1605,9 +1587,8 @@ public:
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg);
- enum Item_result result_type () const { return INT_RESULT; }
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
@@ -1669,8 +1650,8 @@ public:
const Item_equal *item_equal);
Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg, CHARSET_INFO *charset);
- Item_result result_type () const { return STRING_RESULT; }
+ const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation);
uint decimals() const { return NOT_FIXED_DEC; }
int save_in_field(Field *to) { return save_in_field_str(to); }
bool memcpy_field_possible(const Field *from) const
@@ -1690,12 +1671,6 @@ public:
uint repertoire(void) const { return field_repertoire; }
CHARSET_INFO *charset(void) const { return field_charset; }
enum Derivation derivation(void) const { return field_derivation; }
- void set_derivation(enum Derivation derivation_arg,
- uint repertoire_arg)
- {
- field_derivation= derivation_arg;
- field_repertoire= repertoire_arg;
- }
bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_display_length() { return field_length; }
friend class Create_field;
@@ -1737,9 +1712,10 @@ protected:
public:
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg, CHARSET_INFO *charset_arg)
+ const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
- field_name_arg, charset_arg)
+ field_name_arg, collation)
{}
int store_decimal(const my_decimal *d);
@@ -1772,13 +1748,12 @@ public:
Field_real(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, dec_arg, zero_arg, unsigned_arg),
not_fixed(dec_arg >= FLOATING_POINT_DECIMALS)
{}
- Item_result result_type () const { return REAL_RESULT; }
Copy_func *get_copy_func(const Field *from) const
{
return do_field_real;
@@ -1809,13 +1784,13 @@ class Field_decimal :public Field_real {
public:
Field_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
dec_arg, zero_arg, unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_DECIMAL;}
+ const Type_handler *type_handler() const { return &type_handler_olddecimal; }
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
Copy_func *get_copy_func(const Field *from) const
@@ -1857,14 +1832,11 @@ public:
*/
Field_new_decimal(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg,
+ const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool zero_arg, bool unsigned_arg);
- Field_new_decimal(uint32 len_arg, bool maybe_null_arg,
- const char *field_name_arg, uint8 dec_arg,
- bool unsigned_arg);
- enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;}
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
- Item_result result_type () const { return DECIMAL_RESULT; }
Copy_func *get_copy_func(const Field *from) const
{
// if (from->real_type() == MYSQL_TYPE_BIT) // QQ: why?
@@ -1914,7 +1886,6 @@ public:
uint16 mflags, int *order_var);
uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
- static Field *create_from_item(MEM_ROOT *root, Item *);
Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item);
};
@@ -1923,13 +1894,13 @@ class Field_tiny :public Field_num {
public:
Field_tiny(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
bool zero_arg, bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_TINY;}
+ const Type_handler *type_handler() const { return &type_handler_tiny; }
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -1967,18 +1938,19 @@ class Field_short :public Field_num {
public:
Field_short(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
bool zero_arg, bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
- Field_short(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ Field_short(uint32 len_arg,bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg,
bool unsigned_arg)
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, 0, 0, unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_SHORT;}
+ const Type_handler *type_handler() const { return &type_handler_short; }
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2007,13 +1979,13 @@ class Field_medium :public Field_num {
public:
Field_medium(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
bool zero_arg, bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_INT24;}
+ const Type_handler *type_handler() const { return &type_handler_int24; }
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2041,18 +2013,19 @@ class Field_long :public Field_num {
public:
Field_long(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
bool zero_arg, bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
- Field_long(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ Field_long(uint32 len_arg,bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg,
bool unsigned_arg)
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg,0,0,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_LONG;}
+ const Type_handler *type_handler() const { return &type_handler_long; }
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2086,19 +2059,19 @@ class Field_longlong :public Field_num {
public:
Field_longlong(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
bool zero_arg, bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
0, zero_arg,unsigned_arg)
{}
Field_longlong(uint32 len_arg,bool maybe_null_arg,
- const char *field_name_arg,
- bool unsigned_arg)
+ const LEX_CSTRING *field_name_arg,
+ bool unsigned_arg)
:Field_num((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg,0,0,unsigned_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_LONGLONG;}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
int store(const char *to,uint length,CHARSET_INFO *charset);
@@ -2135,7 +2108,7 @@ class Field_float :public Field_real {
public:
Field_float(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
@@ -2144,15 +2117,15 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC;
}
- Field_float(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
- uint8 dec_arg)
+ Field_float(uint32 len_arg, bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg, uint8 dec_arg)
:Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, (uint) 0,
NONE, field_name_arg, dec_arg, 0, 0)
{
if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC;
}
- enum_field_types type() const { return MYSQL_TYPE_FLOAT;}
+ const Type_handler *type_handler() const { return &type_handler_float; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2176,7 +2149,7 @@ class Field_double :public Field_real {
public:
Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint8 dec_arg,bool zero_arg,bool unsigned_arg)
:Field_real(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
@@ -2185,15 +2158,16 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC;
}
- Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
- uint8 dec_arg)
+ Field_double(uint32 len_arg, bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg, uint8 dec_arg)
:Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
NONE, field_name_arg, dec_arg, 0, 0)
{
if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC;
}
- Field_double(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg,
+ Field_double(uint32 len_arg, bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg,
uint8 dec_arg, bool not_fixed_arg)
:Field_real((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "" : 0, (uint) 0,
NONE, field_name_arg, dec_arg, 0, 0)
@@ -2202,7 +2176,7 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC;
}
- enum_field_types type() const { return MYSQL_TYPE_DOUBLE;}
+ const Type_handler *type_handler() const { return &type_handler_double; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2234,12 +2208,12 @@ class Field_null :public Field_str {
static uchar null[1];
public:
Field_null(uchar *ptr_arg, uint32 len_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null, 1,
- unireg_check_arg, field_name_arg, cs)
+ unireg_check_arg, field_name_arg, collation)
{}
- enum_field_types type() const { return MYSQL_TYPE_NULL;}
+ const Type_handler *type_handler() const { return &type_handler_null; }
Copy_func *get_copy_func(const Field *from) const
{
return do_field_string;
@@ -2285,11 +2259,10 @@ protected:
public:
Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg)
{ flags|= BINARY_FLAG; }
- Item_result result_type () const { return STRING_RESULT; }
int store_hex_hybrid(const char *str, uint length)
{
return store(str, length, &my_charset_bin);
@@ -2310,7 +2283,6 @@ public:
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
bool binary() const { return true; }
- enum Item_result cmp_type () const { return TIME_RESULT; }
bool val_bool() { return val_real() != 0e0; }
uint is_equal(Create_field *new_field);
bool eq_def(const Field *field) const
@@ -2364,7 +2336,7 @@ public:
Field_temporal_with_date(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
utype unireg_check_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
{}
@@ -2384,9 +2356,10 @@ protected:
public:
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg,
+ const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share);
- enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;}
+ const Type_handler *type_handler() const { return &type_handler_timestamp; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@@ -2453,7 +2426,7 @@ public:
Field_timestamp_with_dec(uchar *ptr_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint dec_arg) :
Field_timestamp(ptr_arg,
MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg), null_ptr_arg,
@@ -2483,11 +2456,15 @@ public:
class Field_timestamp_hires :public Field_timestamp_with_dec {
+ uint sec_part_bytes(uint dec) const
+ {
+ return Type_handler_timestamp::sec_part_bytes(dec);
+ }
public:
Field_timestamp_hires(uchar *ptr_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint dec_arg) :
Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, share, dec_arg)
@@ -2497,7 +2474,7 @@ public:
my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const;
void store_TIME(my_time_t timestamp, ulong sec_part);
int cmp(const uchar *,const uchar *);
- uint32 pack_length() const;
+ uint32 pack_length() const { return 4 + sec_part_bytes(dec); }
uint size_of() const { return sizeof(*this); }
};
@@ -2515,12 +2492,12 @@ public:
Field_timestampf(uchar *ptr_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint dec_arg) :
Field_timestamp_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, share, dec_arg)
{}
- enum_field_types real_type() const { return MYSQL_TYPE_TIMESTAMP2; }
+ const Type_handler *type_handler() const { return &type_handler_timestamp2; }
enum_field_types binlog_type() const { return MYSQL_TYPE_TIMESTAMP2; }
uint32 pack_length() const
{
@@ -2547,18 +2524,23 @@ class Field_year :public Field_tiny {
public:
Field_year(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
:Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, 1, 1)
{}
- enum_field_types type() const { return MYSQL_TYPE_YEAR;}
+ const Type_handler *type_handler() const { return &type_handler_year; }
Copy_func *get_copy_func(const Field *from) const
{
if (eq_def(from))
return get_identical_copy_func();
switch (from->cmp_type()) {
case STRING_RESULT:
+ {
+ const Type_handler *handler= from->type_handler();
+ if (handler == &type_handler_enum || handler == &type_handler_set)
+ return do_field_int;
return do_field_string;
+ }
case TIME_RESULT:
return do_field_temporal;
case DECIMAL_RESULT:
@@ -2593,10 +2575,10 @@ class Field_date :public Field_temporal_with_date {
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
public:
Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
:Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg) {}
- enum_field_types type() const { return MYSQL_TYPE_DATE;}
+ const Type_handler *type_handler() const { return &type_handler_date; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
@@ -2628,12 +2610,11 @@ class Field_newdate :public Field_temporal_with_date {
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
public:
Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg)
:Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
{}
- enum_field_types type() const { return MYSQL_TYPE_DATE;}
- enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
double val_real(void);
@@ -2667,11 +2648,13 @@ protected:
public:
Field_time(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Field_temporal(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg), curdays(0)
{}
- enum_field_types type() const { return MYSQL_TYPE_TIME;}
+ bool can_be_substituted_to_equal_item(const Context &ctx,
+ const Item_equal *item_equal);
+ const Type_handler *type_handler() const { return &type_handler_time; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
Copy_func *get_copy_func(const Field *from) const
{
@@ -2719,7 +2702,8 @@ protected:
uint dec;
public:
Field_time_with_dec(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg,
+ const LEX_CSTRING *field_name_arg,
uint dec_arg)
:Field_time(ptr_arg, MIN_TIME_WIDTH + dec_arg + MY_TEST(dec_arg),
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg),
@@ -2743,7 +2727,7 @@ class Field_time_hires :public Field_time_with_dec {
void store_TIME(MYSQL_TIME *ltime);
public:
Field_time_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint dec_arg)
:Field_time_with_dec(ptr_arg, null_ptr_arg,
null_bit_arg, unireg_check_arg, field_name_arg,
@@ -2757,7 +2741,7 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
int cmp(const uchar *,const uchar *);
void sort_string(uchar *buff,uint length);
- uint32 pack_length() const;
+ uint32 pack_length() const { return Type_handler_time::hires_bytes(dec); }
uint size_of() const { return sizeof(*this); }
};
@@ -2774,7 +2758,7 @@ class Field_timef :public Field_time_with_dec {
}
public:
Field_timef(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint dec_arg)
:Field_time_with_dec(ptr_arg, null_ptr_arg,
null_bit_arg, unireg_check_arg, field_name_arg,
@@ -2782,7 +2766,7 @@ public:
{
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
}
- enum_field_types real_type() const { return MYSQL_TYPE_TIME2; }
+ const Type_handler *type_handler() const { return &type_handler_time2; }
enum_field_types binlog_type() const { return MYSQL_TYPE_TIME2; }
uint32 pack_length() const
{
@@ -2816,7 +2800,7 @@ class Field_datetime :public Field_temporal_with_date {
public:
Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Field_temporal_with_date(ptr_arg, length_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg)
{
@@ -2824,7 +2808,7 @@ public:
unireg_check == TIMESTAMP_DNUN_FIELD)
flags|= ON_UPDATE_NOW_FLAG;
}
- enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
+ const Type_handler *type_handler() const { return &type_handler_datetime; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; }
double val_real(void);
longlong val_int(void);
@@ -2873,7 +2857,7 @@ protected:
public:
Field_datetime_with_dec(uchar *ptr_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg, uint dec_arg)
+ const LEX_CSTRING *field_name_arg, uint dec_arg)
:Field_datetime(ptr_arg, MAX_DATETIME_WIDTH + dec_arg + MY_TEST(dec_arg),
null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg), dec(dec_arg)
@@ -2909,14 +2893,14 @@ class Field_datetime_hires :public Field_datetime_with_dec {
public:
Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg, uint dec_arg)
+ const LEX_CSTRING *field_name_arg, uint dec_arg)
:Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, dec_arg)
{
DBUG_ASSERT(dec);
}
int cmp(const uchar *,const uchar *);
- uint32 pack_length() const;
+ uint32 pack_length() const { return Type_handler_datetime::hires_bytes(dec); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); }
uint size_of() const { return sizeof(*this); }
@@ -2937,11 +2921,11 @@ class Field_datetimef :public Field_datetime_with_dec {
public:
Field_datetimef(uchar *ptr_arg, uchar *null_ptr_arg,
uchar null_bit_arg, enum utype unireg_check_arg,
- const char *field_name_arg, uint dec_arg)
+ const LEX_CSTRING *field_name_arg, uint dec_arg)
:Field_datetime_with_dec(ptr_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, dec_arg)
{}
- enum_field_types real_type() const { return MYSQL_TYPE_DATETIME2; }
+ const Type_handler *type_handler() const { return &type_handler_datetime2; }
enum_field_types binlog_type() const { return MYSQL_TYPE_DATETIME2; }
uint32 pack_length() const
{
@@ -2967,7 +2951,8 @@ public:
static inline Field_timestamp *
new_Field_timestamp(MEM_ROOT *root,uchar *ptr, uchar *null_ptr, uchar null_bit,
- enum Field::utype unireg_check, const char *field_name,
+ enum Field::utype unireg_check,
+ const LEX_CSTRING *field_name,
TABLE_SHARE *share, uint dec)
{
if (dec==0)
@@ -2983,7 +2968,7 @@ new_Field_timestamp(MEM_ROOT *root,uchar *ptr, uchar *null_ptr, uchar null_bit,
static inline Field_time *
new_Field_time(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit,
- enum Field::utype unireg_check, const char *field_name,
+ enum Field::utype unireg_check, const LEX_CSTRING *field_name,
uint dec)
{
if (dec == 0)
@@ -2999,7 +2984,7 @@ new_Field_time(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit,
static inline Field_datetime *
new_Field_datetime(MEM_ROOT *root, uchar *ptr, uchar *null_ptr, uchar null_bit,
enum Field::utype unireg_check,
- const char *field_name, uint dec)
+ const LEX_CSTRING *field_name, uint dec)
{
if (dec == 0)
return new (root)
@@ -3018,28 +3003,35 @@ class Field_string :public Field_longstr {
public:
Warn_filter_string(const THD *thd, const Field_string *field);
};
+ bool is_var_string() const
+ {
+ return can_alter_field_type &&
+ orig_table &&
+ (orig_table->s->db_create_options & HA_OPTION_PACK_RECORD) &&
+ field_length >= 4 &&
+ orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR;
+ }
public:
bool can_alter_field_type;
Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation)
:Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs),
+ unireg_check_arg, field_name_arg, collation),
can_alter_field_type(1) {};
- Field_string(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
+ Field_string(uint32 len_arg,bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation)
:Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
- NONE, field_name_arg, cs),
+ NONE, field_name_arg, collation),
can_alter_field_type(1) {};
- enum_field_types type() const
+ const Type_handler *type_handler() const
{
- return ((can_alter_field_type && orig_table &&
- orig_table->s->db_create_options & HA_OPTION_PACK_RECORD &&
- field_length >= 4) &&
- orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR ?
- MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
+ if (is_var_string())
+ return &type_handler_var_string;
+ return &type_handler_string;
}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
@@ -3081,7 +3073,6 @@ public:
uint packed_col_length(const uchar *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
- enum_field_types real_type() const { return MYSQL_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
@@ -3111,25 +3102,25 @@ public:
Field_varstring(uchar *ptr_arg,
uint32 len_arg, uint length_bytes_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- TABLE_SHARE *share, CHARSET_INFO *cs)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
+ TABLE_SHARE *share, const DTCollation &collation)
:Field_longstr(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, cs),
+ unireg_check_arg, field_name_arg, collation),
length_bytes(length_bytes_arg)
{
share->varchar_fields++;
}
Field_varstring(uint32 len_arg,bool maybe_null_arg,
- const char *field_name_arg,
- TABLE_SHARE *share, CHARSET_INFO *cs)
+ const LEX_CSTRING *field_name_arg,
+ TABLE_SHARE *share, const DTCollation &collation)
:Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
- NONE, field_name_arg, cs),
+ NONE, field_name_arg, collation),
length_bytes(len_arg < 256 ? 1 :2)
{
share->varchar_fields++;
}
- enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
enum ha_base_keytype key_type() const;
uint row_pack_length() const { return field_length; }
bool zero_pack() const { return 0; }
@@ -3173,7 +3164,6 @@ public:
uint max_packed_col_length(uint max_length);
uint32 data_length();
uint size_of() const { return sizeof(*this); }
- enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
@@ -3188,6 +3178,8 @@ private:
};
+extern LEX_CSTRING temp_lex_str;
+
class Field_blob :public Field_longstr {
protected:
/**
@@ -3210,20 +3202,22 @@ protected:
static void do_conv_blob(Copy_field *copy);
public:
Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
- TABLE_SHARE *share, uint blob_pack_length, CHARSET_INFO *cs);
- Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- CHARSET_INFO *cs)
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
+ TABLE_SHARE *share, uint blob_pack_length,
+ const DTCollation &collation);
+ Field_blob(uint32 len_arg,bool maybe_null_arg, const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation)
:Field_longstr((uchar*) 0, len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
- NONE, field_name_arg, cs),
+ NONE, field_name_arg, collation),
packlength(4)
{
flags|= BLOB_FLAG;
}
- Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- CHARSET_INFO *cs, bool set_packlength)
+ Field_blob(uint32 len_arg,bool maybe_null_arg,
+ const LEX_CSTRING *field_name_arg,
+ const DTCollation &collation, bool set_packlength)
:Field_longstr((uchar*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
- NONE, field_name_arg, cs)
+ NONE, field_name_arg, collation)
{
flags|= BLOB_FLAG;
packlength= 4;
@@ -3235,10 +3229,27 @@ public:
}
}
Field_blob(uint32 packlength_arg)
- :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info),
+ :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, &temp_lex_str,
+ system_charset_info),
packlength(packlength_arg) {}
+ const Type_handler *type_handler() const;
/* Note that the default copy constructor is used, in clone() */
- enum_field_types type() const { return MYSQL_TYPE_BLOB;}
+ enum_field_types type() const
+ {
+ /*
+ We cannot return type_handler()->field_type() here.
+ Some pieces of the code (e.g. in engines) rely on the fact
+ that Field::type(), Field::real_type() and Item_field::field_type()
+ return MYSQL_TYPE_BLOB for all blob variants.
+ We should eventually fix all such code pieces to expect
+ all BLOB type codes.
+ */
+ return MYSQL_TYPE_BLOB;
+ }
+ enum_field_types real_type() const
+ {
+ return MYSQL_TYPE_BLOB;
+ }
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
Copy_func *get_copy_func(const Field *from) const
@@ -3417,18 +3428,25 @@ public:
enum storage_type storage;
Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
TABLE_SHARE *share, uint blob_pack_length,
enum geometry_type geom_type_arg, uint field_srid)
- :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
+ :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
field_name_arg, share, blob_pack_length, &my_charset_bin)
{ geom_type= geom_type_arg; srid= field_srid; }
- Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
- TABLE_SHARE *share, enum geometry_type geom_type_arg)
- :Field_blob(len_arg, maybe_null_arg, field_name_arg, &my_charset_bin)
- { geom_type= geom_type_arg; srid= 0; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
- enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; }
+ const Type_handler *type_handler() const
+ {
+ return &type_handler_geometry;
+ }
+ enum_field_types type() const
+ {
+ return MYSQL_TYPE_GEOMETRY;
+ }
+ enum_field_types real_type() const
+ {
+ return MYSQL_TYPE_GEOMETRY;
+ }
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const;
@@ -3474,19 +3492,18 @@ public:
TYPELIB *typelib;
Field_enum(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint packlength_arg,
TYPELIB *typelib_arg,
- CHARSET_INFO *charset_arg)
+ const DTCollation &collation)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, charset_arg),
+ unireg_check_arg, field_name_arg, collation),
packlength(packlength_arg),typelib(typelib_arg)
{
flags|=ENUM_FLAG;
}
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
- enum_field_types type() const { return MYSQL_TYPE_STRING; }
- enum Item_result cmp_type () const { return INT_RESULT; }
+ const Type_handler *type_handler() const { return &type_handler_enum; }
enum ha_base_keytype key_type() const;
Copy_func *get_copy_func(const Field *from) const
{
@@ -3527,7 +3544,6 @@ public:
void store_type(ulonglong value);
void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); }
- enum_field_types real_type() const { return MYSQL_TYPE_ENUM; }
uint pack_length_from_metadata(uint field_metadata)
{ return (field_metadata & 0x00ff); }
uint row_pack_length() const { return pack_length(); }
@@ -3538,6 +3554,7 @@ public:
/* enum and set are sorted as integers */
CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; }
uint decimals() const { return 0; }
+ TYPELIB *get_typelib() const { return typelib; }
virtual uchar *pack(uchar *to, const uchar *from, uint max_length);
virtual const uchar *unpack(uchar *to, const uchar *from,
@@ -3557,6 +3574,9 @@ public:
*/
return false;
}
+ bool can_optimize_range(const Item_bool_func *cond,
+ const Item *item,
+ bool is_eq_func) const;
private:
int do_save_field_metadata(uchar *first_byte);
uint is_equal(Create_field *new_field);
@@ -3567,14 +3587,14 @@ class Field_set :public Field_enum {
public:
Field_set(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg,
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
uint32 packlength_arg,
- TYPELIB *typelib_arg, CHARSET_INFO *charset_arg)
+ TYPELIB *typelib_arg, const DTCollation &collation)
:Field_enum(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg,
packlength_arg,
- typelib_arg,charset_arg),
- empty_set_string("", 0, charset_arg)
+ typelib_arg, collation),
+ empty_set_string("", 0, collation.collation)
{
flags=(flags & ~ENUM_FLAG) | SET_FLAG;
}
@@ -3587,7 +3607,7 @@ public:
String *val_str(String*,String *);
void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); }
- enum_field_types real_type() const { return MYSQL_TYPE_SET; }
+ const Type_handler *type_handler() const { return &type_handler_set; }
bool has_charset(void) const { return TRUE; }
private:
const String empty_set_string;
@@ -3616,14 +3636,13 @@ public:
uint bytes_in_rec;
Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
- enum utype unireg_check_arg, const char *field_name_arg);
- enum_field_types type() const { return MYSQL_TYPE_BIT; }
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg);
+ const Type_handler *type_handler() const { return &type_handler_bit; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
uint32 max_data_length() const { return (field_length + 7) / 8; }
uint32 max_display_length() { return field_length; }
uint size_of() const { return sizeof(*this); }
- Item_result result_type () const { return INT_RESULT; }
int reset(void) {
bzero(ptr, bytes_in_rec);
if (bit_ptr && (bit_len > 0)) // reset odd bits among null bits
@@ -3752,7 +3771,7 @@ class Field_bit_as_char: public Field_bit {
public:
Field_bit_as_char(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
- enum utype unireg_check_arg, const char *field_name_arg);
+ enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg);
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
uint size_of() const { return sizeof(*this); }
int store(const char *to, uint length, CHARSET_INFO *charset);
@@ -3763,28 +3782,68 @@ public:
};
-extern const LEX_STRING null_lex_str;
-
+extern const LEX_CSTRING null_clex_str;
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
uchar *ptr, uint32 field_length,
uchar *null_pos, uchar null_bit,
- uint pack_flag, enum_field_types field_type,
+ uint pack_flag, const Type_handler *handler,
CHARSET_INFO *cs,
Field::geometry_type geom_type, uint srid,
Field::utype unireg_check,
- TYPELIB *interval, const char *field_name);
+ TYPELIB *interval, const LEX_CSTRING *field_name);
/*
Create field class for CREATE TABLE
*/
-class Column_definition: public Sql_alloc
+class Column_definition: public Sql_alloc,
+ public Type_handler_hybrid_field_type
{
+ /**
+ Create "interval" from "interval_list".
+ @param mem_root - memory root to create the TYPELIB
+ instance and its values on
+ @param reuse_interval_list_values - determines if TYPELIB can reuse strings
+ from interval_list, or should always
+ allocate a copy on mem_root, even if
+ character set conversion is not needed
+ @retval false on success
+ @retval true on error (bad values, or EOM)
+ */
+ bool create_interval_from_interval_list(MEM_ROOT *mem_root,
+ bool reuse_interval_list_values);
+
+ /*
+ Calculate TYPELIB (set or enum) max and total lengths
+
+ @param cs charset+collation pair of the interval
+ @param max_length length of the longest item
+ @param tot_length sum of the item lengths
+
+ After this method call:
+ - ENUM uses max_length
+ - SET uses tot_length.
+ */
+ void calculate_interval_lengths(uint32 *max_length, uint32 *tot_length)
+ {
+ const char **pos;
+ uint *len;
+ *max_length= *tot_length= 0;
+ for (pos= interval->type_names, len= interval->type_lengths;
+ *pos ; pos++, len++)
+ {
+ size_t length= charset->cset->numchars(charset, *pos, *pos + *len);
+ *tot_length+= length;
+ set_if_bigger(*max_length, (uint32)length);
+ }
+ }
+ bool prepare_stage1_check_typelib_default();
+ bool prepare_stage1_convert_default(THD *, MEM_ROOT *, CHARSET_INFO *to);
+ const Type_handler *field_type() const; // Prevent using this
public:
- const char *field_name;
- LEX_STRING comment; // Comment for field
+ LEX_CSTRING field_name;
+ LEX_CSTRING comment; // Comment for field
Item *on_update; // ON UPDATE NOW()
- enum enum_field_types sql_type;
/*
At various stages in execution this can be length of field in bytes or
max number of characters.
@@ -3816,19 +3875,111 @@ public:
*default_value, // Default value
*check_constraint; // Check constraint
- Column_definition():
- comment(null_lex_str),
- on_update(0), sql_type(MYSQL_TYPE_NULL),
+ Column_definition()
+ :Type_handler_hybrid_field_type(&type_handler_null),
+ comment(null_clex_str),
+ on_update(NULL), length(0), decimals(0),
flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
- interval(0), srid(0), geom_type(Field::GEOM_GEOMETRY),
- option_list(NULL),
+ interval(0), charset(&my_charset_bin),
+ srid(0), geom_type(Field::GEOM_GEOMETRY),
+ option_list(NULL), pack_flag(0),
vcol_info(0), default_value(0), check_constraint(0)
{
interval_list.empty();
}
-
Column_definition(THD *thd, Field *field, Field *orig_field);
- void create_length_to_internal_length(void);
+ void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs);
+ void create_length_to_internal_length_null()
+ {
+ DBUG_ASSERT(length == 0);
+ key_length= pack_length= 0;
+ }
+ void create_length_to_internal_length_simple()
+ {
+ key_length= pack_length= type_handler()->calc_pack_length(length);
+ }
+ void create_length_to_internal_length_string()
+ {
+ length*= charset->mbmaxlen;
+ key_length= length;
+ pack_length= type_handler()->calc_pack_length(length);
+ }
+ void create_length_to_internal_length_typelib()
+ {
+ /* Pack_length already calculated in sql_parse.cc */
+ length*= charset->mbmaxlen;
+ key_length= pack_length;
+ }
+ void create_length_to_internal_length_bit();
+ void create_length_to_internal_length_newdecimal();
+
+ /**
+ Prepare a SET/ENUM field.
+ Create "interval" from "interval_list" if needed, and adjust "length".
+ @param mem_root - Memory root to allocate TYPELIB and
+ its values on
+ @param reuse_interval_list_values - determines if TYPELIB can reuse value
+ buffers from interval_list, or should
+ always allocate a copy on mem_root,
+ even if character set conversion
+ is not needed
+ */
+ bool prepare_interval_field(MEM_ROOT *mem_root,
+ bool reuse_interval_list_values);
+
+ void prepare_interval_field_calc_length()
+ {
+ uint32 field_length, dummy;
+ if (real_field_type() == MYSQL_TYPE_SET)
+ {
+ calculate_interval_lengths(&dummy, &field_length);
+ length= field_length + (interval->count - 1);
+ }
+ else /* MYSQL_TYPE_ENUM */
+ {
+ calculate_interval_lengths(&field_length, &dummy);
+ length= field_length;
+ }
+ set_if_smaller(length, MAX_FIELD_WIDTH - 1);
+ }
+
+ bool prepare_blob_field(THD *thd);
+
+ bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root);
+
+ bool prepare_stage1(THD *thd, MEM_ROOT *mem_root,
+ handler *file, ulonglong table_flags);
+ bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root,
+ handler *file, ulonglong table_flags);
+ bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root,
+ handler *file, ulonglong table_flags);
+ bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root,
+ handler *file, ulonglong table_flags);
+
+ void redefine_stage1_common(const Column_definition *dup_field,
+ const handler *file,
+ const Schema_specification_st *schema);
+ bool redefine_stage1(const Column_definition *dup_field, const handler *file,
+ const Schema_specification_st *schema)
+ {
+ const Type_handler *handler= dup_field->type_handler();
+ return handler->Column_definition_redefine_stage1(this, dup_field,
+ file, schema);
+ }
+ bool prepare_stage2(handler *handler, ulonglong table_flags);
+ bool prepare_stage2_blob(handler *handler,
+ ulonglong table_flags, uint field_flags);
+ bool prepare_stage2_varchar(ulonglong table_flags);
+ bool prepare_stage2_typelib(const char *type_name, uint field_flags,
+ uint *dup_val_count);
+ uint pack_flag_numeric(uint dec) const;
+ uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; }
+ bool check_length(uint mysql_errno, uint max_allowed_length) const;
+ bool fix_attributes_real(uint default_length);
+ bool fix_attributes_int(uint default_length);
+ bool fix_attributes_decimal();
+ bool fix_attributes_temporal_with_time(uint int_part_length);
+ bool fix_attributes_bit();
bool check(THD *thd);
@@ -3853,16 +4004,16 @@ public:
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
uchar *ptr, uchar *null_pos, uchar null_bit,
- const char *field_name_arg) const
+ const LEX_CSTRING *field_name_arg) const
{
return ::make_field(share, mem_root, ptr,
(uint32)length, null_pos, null_bit,
- pack_flag, sql_type, charset,
+ pack_flag, type_handler(), charset,
geom_type, srid, unireg_check, interval,
field_name_arg);
}
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg) const
{
return make_field(share, mem_root, (uchar *) 0, (uchar *) "", 0,
field_name_arg);
@@ -3875,14 +4026,158 @@ public:
return unireg_check == Field::TIMESTAMP_DN_FIELD
|| unireg_check == Field::TIMESTAMP_DNUN_FIELD;
}
+
+ // Replace the entire value by another definition
+ void set_column_definition(const Column_definition *def)
+ {
+ *this= *def;
+ }
+};
+
+
+/**
+ List of ROW element definitions, e.g.:
+ DECLARE a ROW(a INT,b VARCHAR(10))
+*/
+class Row_definition_list: public List<class Spvar_definition>
+{
+public:
+ inline bool eq_name(const Spvar_definition *def, const LEX_CSTRING *name) const;
+ /**
+ Find a ROW field by name.
+ @param [IN] name - the name
+ @param [OUT] offset - if the ROW field found, its offset it returned here
+ @retval NULL - the ROW field was not found
+ @retval !NULL - the pointer to the found ROW field
+ */
+ Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const
+ {
+ // Cast-off the "const" qualifier
+ List_iterator<Spvar_definition> it(*((List<Spvar_definition>*)this));
+ Spvar_definition *def;
+ for (*offset= 0; (def= it++); (*offset)++)
+ {
+ if (eq_name(def, name))
+ return def;
+ }
+ return 0;
+ }
+};
+
+
+/**
+ This class is used during a stored routine or a trigger execution,
+ at sp_rcontext::create() time.
+ Currently it can represent:
+ - variables with explicit data types: DECLARE a INT;
+ - variables with data type references: DECLARE a t1.a%TYPE;
+ - ROW type variables
+
+ Notes:
+ - Scalar variables have m_field_definitions==NULL.
+ - ROW variables are defined as having MYSQL_TYPE_NULL,
+ with a non-empty m_field_definitions.
+
+ Data type references to other object types will be added soon, e.g.:
+ - DECLARE a table_name%ROWTYPE;
+ - DECLARE a cursor_name%ROWTYPE;
+ - DECLARE a record_name%TYPE;
+ - DECLARE a variable_name%TYPE;
+*/
+class Spvar_definition: public Column_definition
+{
+ class Qualified_column_ident *m_column_type_ref; // for %TYPE
+ class Table_ident *m_table_rowtype_ref; // for table%ROWTYPE
+ bool m_cursor_rowtype_ref; // for cursor%ROWTYPE
+ Row_definition_list *m_row_field_definitions; // for ROW
+public:
+ Spvar_definition()
+ :m_column_type_ref(NULL),
+ m_table_rowtype_ref(NULL),
+ m_cursor_rowtype_ref(false),
+ m_row_field_definitions(NULL)
+ { }
+ Spvar_definition(THD *thd, Field *field)
+ :Column_definition(thd, field, NULL),
+ m_column_type_ref(NULL),
+ m_table_rowtype_ref(NULL),
+ m_cursor_rowtype_ref(false),
+ m_row_field_definitions(NULL)
+ { }
+ const Type_handler *type_handler() const
+ {
+ return is_row() || is_table_rowtype_ref() || is_cursor_rowtype_ref() ?
+ &type_handler_row :
+ Type_handler_hybrid_field_type::type_handler();
+ }
+ bool is_column_type_ref() const { return m_column_type_ref != 0; }
+ bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; }
+ bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref; }
+ class Qualified_column_ident *column_type_ref() const
+ {
+ return m_column_type_ref;
+ }
+ void set_column_type_ref(class Qualified_column_ident *ref)
+ {
+ m_column_type_ref= ref;
+ }
+
+ class Table_ident *table_rowtype_ref() const
+ {
+ return m_table_rowtype_ref;
+ }
+ void set_table_rowtype_ref(class Table_ident *ref)
+ {
+ m_table_rowtype_ref= ref;
+ }
+ void set_cursor_rowtype_ref(bool ref)
+ {
+ m_cursor_rowtype_ref= ref;
+ }
+
+ /*
+ Find a ROW field by name.
+ See Row_field_list::find_row_field_by_name() for details.
+ */
+ Spvar_definition *find_row_field_by_name(const LEX_CSTRING *name, uint *offset) const
+ {
+ DBUG_ASSERT(m_row_field_definitions);
+ return m_row_field_definitions->find_row_field_by_name(name, offset);
+ }
+ uint is_row() const
+ {
+ return m_row_field_definitions != NULL;
+ }
+ // Check if "this" defines a ROW variable with n elements
+ uint is_row(uint n) const
+ {
+ return m_row_field_definitions != NULL &&
+ m_row_field_definitions->elements == n;
+ }
+ Row_definition_list *row_field_definitions() const
+ {
+ return m_row_field_definitions;
+ }
+ void set_row_field_definitions(Row_definition_list *list)
+ {
+ m_row_field_definitions= list;
+ }
+
};
+inline bool Row_definition_list::eq_name(const Spvar_definition *def,
+ const LEX_CSTRING *name) const
+{
+ return def->field_name.length == name->length && my_strcasecmp(system_charset_info, def->field_name.str, name->str) == 0;
+}
+
+
class Create_field :public Column_definition
{
public:
- const char *change; // If done with alter table
- const char *after; // Put column after this one
+ LEX_CSTRING change; // If done with alter table
+ LEX_CSTRING after; // Put column after this one
Field *field; // For alter table
TYPELIB *save_interval; // Temporary copy for the above
// Used only for UCS2 intervals
@@ -3894,16 +4189,20 @@ public:
bool create_if_not_exists; // Used in ALTER TABLE IF NOT EXISTS
Create_field():
- Column_definition(), change(0), after(0),
+ Column_definition(),
field(0), option_struct(NULL),
create_if_not_exists(false)
- { }
+ {
+ change= after= null_clex_str;
+ }
Create_field(THD *thd, Field *old_field, Field *orig_field):
Column_definition(thd, old_field, orig_field),
- change(old_field->field_name), after(0),
+ change(old_field->field_name),
field(old_field), option_struct(old_field->option_struct),
create_if_not_exists(false)
- { }
+ {
+ after= null_clex_str;
+ }
/* Used to make a clone of this object for ALTER/CREATE TABLE */
Create_field *clone(MEM_ROOT *mem_root) const;
};
@@ -3917,9 +4216,9 @@ class Send_field :public Sql_alloc {
public:
const char *db_name;
const char *table_name,*org_table_name;
- const char *col_name,*org_col_name;
+ LEX_CSTRING col_name, org_col_name;
ulong length;
- uint charsetnr, flags, decimals;
+ uint flags, decimals;
enum_field_types type;
Send_field() {}
};
@@ -3967,11 +4266,10 @@ public:
uint pack_length_to_packflag(uint type);
enum_field_types get_blob_type_from_length(ulong length);
-uint32 calc_pack_length(enum_field_types type,uint32 length);
int set_field_to_null(Field *field);
int set_field_to_null_with_conversions(Field *field, bool no_conversions);
int convert_null_to_field_value_or_error(Field *field);
-bool check_expression(Virtual_column_info *vcol, const char *name,
+bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
enum_vcol_info_type type);
/*
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 85101fd5f0a..a744af76626 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -125,7 +125,7 @@ static int set_bad_null_error(Field *field, int err)
return 0;
case CHECK_FIELD_ERROR_FOR_NULL:
if (!field->table->in_use->no_errors)
- my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
+ my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name.str);
return -1;
}
DBUG_ASSERT(0); // impossible
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 2388dd759b5..31ff2e511a9 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -563,7 +563,8 @@ const char* dbug_print_table_row(TABLE *table)
else
output.append(",");
- output.append((*pfield)->field_name? (*pfield)->field_name: "NULL");
+ output.append((*pfield)->field_name.str ?
+ (*pfield)->field_name.str: "NULL");
}
output.append(")=(");
@@ -614,7 +615,8 @@ static void dbug_print_record(TABLE *table, bool print_rowid)
fprintf(DBUG_FILE, "record (");
for (pfield= table->field; *pfield ; pfield++)
- fprintf(DBUG_FILE, "%s%s", (*pfield)->field_name, (pfield[1])? ", ":"");
+ fprintf(DBUG_FILE, "%s%s", (*pfield)->field_name.str,
+ (pfield[1])? ", ":"");
fprintf(DBUG_FILE, ") = ");
fprintf(DBUG_FILE, "(");
@@ -1178,7 +1180,8 @@ static void make_sortkey(register Sort_param *param,
}
else
{ // Item
- sort_field->item->make_sort_key(to, sort_field->item, sort_field, param);
+ sort_field->item->type_handler()->make_sort_key(to, sort_field->item,
+ sort_field, param);
if ((maybe_null= sort_field->item->maybe_null))
to++;
}
@@ -1967,7 +1970,8 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
}
else
{
- sortorder->item->sortlength(thd, sortorder->item, sortorder);
+ sortorder->item->type_handler()->sortlength(thd, sortorder->item,
+ sortorder);
if (use_strnxfrm(sortorder->item->collation.collation))
{
*multi_byte_charset= true;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 2c91dfa0c65..dae6eb32afc 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -77,7 +77,9 @@
HA_DUPLICATE_POS | \
HA_CAN_SQL_HANDLER | \
HA_CAN_INSERT_DELAYED | \
- HA_READ_BEFORE_WRITE_REMOVAL)
+ HA_READ_BEFORE_WRITE_REMOVAL |\
+ HA_CAN_TABLES_WITHOUT_ROLLBACK)
+
static const char *ha_par_ext= ".par";
/****************************************************************************
@@ -1529,8 +1531,8 @@ int ha_partition::prepare_new_partition(TABLE *tbl,
That file name may be different from part_name, which will be
attached in append_file_to_dir().
*/
- truncate_partition_filename(p_elem->data_file_name);
- truncate_partition_filename(p_elem->index_file_name);
+ truncate_partition_filename((char*) p_elem->data_file_name);
+ truncate_partition_filename((char*) p_elem->index_file_name);
if ((error= set_up_table_before_create(tbl, part_name, create_info, p_elem)))
goto error_create;
@@ -2112,7 +2114,7 @@ void ha_partition::update_create_info(HA_CREATE_INFO *create_info)
my_bool from_alter = (create_info->data_file_name == (const char*) -1);
create_info->data_file_name= create_info->index_file_name = NULL;
- create_info->connect_string= null_lex_str;
+ create_info->connect_string= null_clex_str;
/*
We do not need to update the individual partition DATA DIRECTORY settings
@@ -2987,27 +2989,29 @@ bool ha_partition::read_par_file(const char *name)
m_file_buffer= file_buffer; // Will be freed in clear_handler_file()
m_name_buffer_ptr= (char*) (tot_name_len_offset + PAR_WORD_SIZE);
- if (!(m_connect_string= (LEX_STRING*)
- alloc_root(&m_mem_root, m_tot_parts * sizeof(LEX_STRING))))
+ if (!(m_connect_string= (LEX_CSTRING*)
+ alloc_root(&m_mem_root, m_tot_parts * sizeof(LEX_CSTRING))))
goto err2;
- bzero(m_connect_string, m_tot_parts * sizeof(LEX_STRING));
+ bzero(m_connect_string, m_tot_parts * sizeof(LEX_CSTRING));
/* Read connection arguments (for federated X engine) */
for (i= 0; i < m_tot_parts; i++)
{
- LEX_STRING connect_string;
+ LEX_CSTRING connect_string;
uchar buffer[4];
+ char *tmp;
if (my_read(file, buffer, 4, MYF(MY_NABP)))
{
/* No extra options; Probably not a federatedx engine */
break;
}
connect_string.length= uint4korr(buffer);
- connect_string.str= (char*) alloc_root(&m_mem_root, connect_string.length+1);
+ connect_string.str= tmp= (char*) alloc_root(&m_mem_root,
+ connect_string.length+1);
if (my_read(file, (uchar*) connect_string.str, connect_string.length,
MYF(MY_NABP)))
break;
- connect_string.str[connect_string.length]= 0;
+ tmp[connect_string.length]= 0;
m_connect_string[i]= connect_string;
}
@@ -4236,7 +4240,7 @@ exit:
old_data is always record[1]
*/
-int ha_partition::update_row(const uchar *old_data, uchar *new_data)
+int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
{
THD *thd= ha_thd();
uint32 new_part_id, old_part_id;
@@ -4312,7 +4316,7 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
DBUG_PRINT("info", ("Update from partition %d to partition %d",
old_part_id, new_part_id));
tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */
- error= m_file[new_part_id]->ha_write_row(new_data);
+ error= m_file[new_part_id]->ha_write_row((uchar*) new_data);
reenable_binlog(thd);
table->next_number_field= saved_next_number_field;
if (error)
@@ -7179,6 +7183,7 @@ int ha_partition::extra(enum ha_extra_function operation)
case HA_EXTRA_QUICK:
case HA_EXTRA_PREPARE_FOR_DROP:
case HA_EXTRA_FLUSH_CACHE:
+ case HA_EXTRA_PREPARE_FOR_ALTER_TABLE:
{
DBUG_RETURN(loop_extra(operation));
}
@@ -7983,7 +7988,7 @@ void ha_partition::append_row_to_str(String &str)
{
Field *field= key_part->field;
str.append(" ");
- str.append(field->field_name);
+ str.append(&field->field_name);
str.append(":");
field_unpack(&str, field, rec, 0, false);
}
@@ -8003,7 +8008,7 @@ void ha_partition::append_row_to_str(String &str)
{
Field *field= *field_ptr;
str.append(" ");
- str.append(field->field_name);
+ str.append(&field->field_name);
str.append(":");
field_unpack(&str, field, rec, 0, false);
}
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index a5a584287cf..6c2c10c059e 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -137,7 +137,7 @@ private:
handler **m_new_file; // Array of references to new handlers
handler **m_reorged_file; // Reorganised partitions
handler **m_added_file; // Added parts kept for errors
- LEX_STRING *m_connect_string;
+ LEX_CSTRING *m_connect_string;
partition_info *m_part_info; // local reference to partition
Field **m_part_field_array; // Part field array locally to save acc
uchar *m_ordered_rec_buffer; // Row and key buffer for ord. idx scan
@@ -422,6 +422,8 @@ public:
virtual THR_LOCK_DATA **store_lock(THD * thd, THR_LOCK_DATA ** to,
enum thr_lock_type lock_type);
virtual int external_lock(THD * thd, int lock_type);
+ LEX_CSTRING *engine_name()
+ { return hton_name(table->part_info->default_engine_type); }
/*
When table is locked a statement is started by calling start_stmt
instead of external_lock
@@ -477,7 +479,7 @@ public:
number of calls to write_row.
*/
virtual int write_row(uchar * buf);
- virtual int update_row(const uchar * old_data, uchar * new_data);
+ virtual int update_row(const uchar * old_data, const uchar * new_data);
virtual int delete_row(const uchar * buf);
virtual int delete_all_rows(void);
virtual int truncate();
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
new file mode 100644
index 00000000000..7f2248bf3cb
--- /dev/null
+++ b/sql/ha_sequence.cc
@@ -0,0 +1,438 @@
+/*
+ Copyright (c) 2017, Aliyun and/or its affiliates.
+ Copyright (c) 2017, MariaDB corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <my_global.h>
+#include "sql_list.h"
+#include "table.h"
+#include "sql_sequence.h"
+#include "ha_sequence.h"
+#include "sql_plugin.h"
+#include "mysql/plugin.h"
+#include "sql_priv.h"
+#include "sql_parse.h"
+#include "sql_table.h"
+#include "sql_update.h"
+#include "sql_base.h"
+#include "log_event.h"
+
+/*
+ Table flags we should inherit and disable from the original engine.
+ We add HA_STATS_RECORDS_IS_EXACT as ha_sequence::info() will ensure
+ that records is always 1
+*/
+
+#define SEQUENCE_ENABLED_TABLE_FLAGS (HA_STATS_RECORDS_IS_EXACT | \
+ HA_PERSISTENT_TABLE)
+#define SEQUENCE_DISABLED_TABLE_FLAGS (HA_CAN_SQL_HANDLER | \
+ HA_CAN_INSERT_DELAYED | \
+ HA_BINLOG_STMT_CAPABLE)
+handlerton *sql_sequence_hton;
+
+/*
+ Create a sequence handler
+*/
+
+ha_sequence::ha_sequence(handlerton *hton, TABLE_SHARE *share)
+ :handler(hton, share), write_locked(0)
+{
+ sequence= share->sequence;
+ DBUG_ASSERT(share->sequence);
+}
+
+/**
+ Destructor method must remove the underlying handler
+*/
+ha_sequence::~ha_sequence()
+{
+ delete file;
+}
+
+/**
+ Sequence table open method
+
+ @param name Path to file (dbname and tablename)
+ @param mode mode
+ @param flags Flags how to open file
+
+ RETURN VALUES
+ @retval 0 Success
+ @retval != 0 Failure
+*/
+
+int ha_sequence::open(const char *name, int mode, uint flags)
+{
+ int error;
+ DBUG_ENTER("ha_sequence::open");
+ DBUG_ASSERT(table->s == table_share && file);
+
+ file->table= table;
+ if (!(error= file->open(name, mode, flags)))
+ {
+ /*
+ Copy values set by handler::open() in the underlying handler
+ Reuse original storage engine data for duplicate key reference
+ It would be easier to do this if we would have another handler
+ call: fixup_after_open()...
+ */
+ ref= file->ref;
+ ref_length= file->ref_length;
+ dup_ref= file->dup_ref;
+
+ /*
+ ha_open() sets the following for us. We have to set this for the
+ underlying handler
+ */
+ file->cached_table_flags= file->table_flags();
+
+ file->reset_statistics();
+ internal_tmp_table= file->internal_tmp_table=
+ MY_TEST(flags & HA_OPEN_INTERNAL_TABLE);
+ reset_statistics();
+
+ /* Don't try to read the inital row the call is part of create code */
+ if (!(flags & (HA_OPEN_FOR_CREATE | HA_OPEN_FOR_REPAIR)))
+ {
+ if ((error= table->s->sequence->read_initial_values(table)))
+ file->ha_close();
+ }
+ else
+ table->m_needs_reopen= true;
+ }
+ DBUG_RETURN(error);
+}
+
+/*
+ Clone the sequence. Needed if table is used by range optimization
+ (Very, very unlikely)
+*/
+
+handler *ha_sequence::clone(const char *name, MEM_ROOT *mem_root)
+{
+ ha_sequence *new_handler;
+ DBUG_ENTER("ha_sequence::clone");
+ if (!(new_handler= new (mem_root) ha_sequence(ht, table_share)))
+ DBUG_RETURN(NULL);
+
+ /*
+ Allocate new_handler->ref here because otherwise ha_open will allocate it
+ on this->table->mem_root and we will not be able to reclaim that memory
+ when the clone handler object is destroyed.
+ */
+
+ if (!(new_handler->ref= (uchar*) alloc_root(mem_root,
+ ALIGN_SIZE(ref_length)*2)))
+ goto err;
+
+ if (new_handler->ha_open(table, name,
+ table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_NO_PSI_CALL))
+ goto err;
+
+ /* Reuse original storage engine data for duplicate key reference */
+ new_handler->ref= file->ref;
+ new_handler->ref_length= file->ref_length;
+ new_handler->dup_ref= file->dup_ref;
+
+ DBUG_RETURN((handler*) new_handler);
+
+err:
+ delete new_handler;
+ DBUG_RETURN(NULL);
+}
+
+
+/*
+ Map the create table to the original storage engine
+*/
+
+int ha_sequence::create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info)
+{
+ DBUG_ASSERT(create_info->sequence);
+ /* Sequence tables has one and only one row */
+ create_info->max_rows= create_info->min_rows= 1;
+ return (file->create(name, form, create_info));
+}
+
+/**
+ Sequence write row method.
+
+ A sequence table has only one row. Any inserts in the table
+ will update this row.
+
+ @retval 0 Success
+ @retval != 0 Failure
+
+ NOTES:
+ write_locked is set if we are called from SEQUENCE::next_value
+ In this case the mutex is already locked and we should not update
+ the sequence with 'buf' as the sequence object is already up to date.
+*/
+
+int ha_sequence::write_row(uchar *buf)
+{
+ int error;
+ sequence_definition tmp_seq;
+ bool sequence_locked;
+ DBUG_ENTER("ha_sequence::write_row");
+ DBUG_ASSERT(table->record[0] == buf);
+
+ row_already_logged= 0;
+ if (unlikely(sequence->initialized == SEQUENCE::SEQ_IN_PREPARE))
+ {
+ /* This calls is from ha_open() as part of create table */
+ DBUG_RETURN(file->write_row(buf));
+ }
+ if (unlikely(sequence->initialized == SEQUENCE::SEQ_IN_ALTER))
+ {
+ int error= 0;
+ /* This is called from alter table */
+ tmp_seq.read_fields(table);
+ if (tmp_seq.check_and_adjust(0))
+ DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
+ sequence->copy(&tmp_seq);
+ if (!(error= file->write_row(buf)))
+ sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
+ DBUG_RETURN(error);
+ }
+ if (unlikely(sequence->initialized != SEQUENCE::SEQ_READY_TO_USE))
+ DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+
+ sequence_locked= write_locked;
+ if (!write_locked) // If not from next_value()
+ {
+ /*
+ User tries to write a full row directly to the sequence table with
+ INSERT or LOAD DATA.
+
+ - Get an exclusive lock for the table. This is needed to ensure that
+ we excute all full inserts (same as ALTER SEQUENCE) in same order
+ on master and slaves
+ - Check that we are only using one table.
+ This is to avoid deadlock problems when upgrading lock to exlusive.
+ - Check that the new row is an accurate SEQUENCE object
+ */
+
+ THD *thd= table->in_use;
+ if (thd->lock->table_count != 1)
+ DBUG_RETURN(ER_WRONG_INSERT_INTO_SEQUENCE);
+ if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE,
+ thd->variables.lock_wait_timeout))
+ DBUG_RETURN(ER_LOCK_WAIT_TIMEOUT);
+
+ tmp_seq.read_fields(table);
+ if (tmp_seq.check_and_adjust(0))
+ DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
+
+ /*
+ Lock sequence to ensure that no one can come in between
+ while sequence, table and binary log are updated.
+ */
+ sequence->write_lock(table);
+ }
+
+ if (!(error= file->update_first_row(buf)))
+ {
+ Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
+ if (!sequence_locked)
+ sequence->copy(&tmp_seq);
+ rows_changed++;
+ /* We have to do the logging while we hold the sequence mutex */
+ error= binlog_log_row(table, 0, buf, log_func);
+ row_already_logged= 1;
+ }
+
+ sequence->all_values_used= 0;
+ if (!sequence_locked)
+ sequence->write_unlock(table);
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Inherit the sequence base table flags.
+*/
+
+handler::Table_flags ha_sequence::table_flags() const
+{
+ DBUG_ENTER("ha_sequence::table_flags");
+ DBUG_RETURN((file->table_flags() & ~SEQUENCE_DISABLED_TABLE_FLAGS) |
+ SEQUENCE_ENABLED_TABLE_FLAGS);
+}
+
+
+int ha_sequence::info(uint flag)
+{
+ DBUG_ENTER("ha_sequence::info");
+ file->info(flag);
+ /* Inform optimizer that we have always only one record */
+ stats= file->stats;
+ stats.records= 1;
+ DBUG_RETURN(false);
+}
+
+
+int ha_sequence::extra(enum ha_extra_function operation)
+{
+ if (operation == HA_EXTRA_PREPARE_FOR_ALTER_TABLE)
+ {
+ /* In case of ALTER TABLE allow ::write_row() to copy rows */
+ sequence->initialized= SEQUENCE::SEQ_IN_ALTER;
+ }
+ return file->extra(operation);
+}
+
+bool ha_sequence::check_if_incompatible_data(HA_CREATE_INFO *create_info,
+ uint table_changes)
+{
+ /* Table definition is locked for SEQUENCE tables */
+ return(COMPATIBLE_DATA_YES);
+}
+
+
+int ha_sequence::external_lock(THD *thd, int lock_type)
+{
+ int error= file->external_lock(thd, lock_type);
+
+ /*
+ Copy lock flag to satisfy DBUG_ASSERT checks in ha_* functions in
+ handler.cc when we later call it with file->ha_..()
+ */
+ file->m_lock_type= lock_type;
+ return error;
+}
+
+/*
+ Squence engine error deal method
+*/
+
+void ha_sequence::print_error(int error, myf errflag)
+{
+ const char *sequence_db= table_share->db.str;
+ const char *sequence_name= table_share->table_name.str;
+ DBUG_ENTER("ha_sequence::print_error");
+
+ switch (error) {
+ case HA_ERR_SEQUENCE_INVALID_DATA:
+ {
+ my_error(ER_SEQUENCE_INVALID_DATA, MYF(errflag), sequence_db,
+ sequence_name);
+ DBUG_VOID_RETURN;
+ }
+ case HA_ERR_SEQUENCE_RUN_OUT:
+ {
+ my_error(ER_SEQUENCE_RUN_OUT, MYF(errflag), sequence_db, sequence_name);
+ DBUG_VOID_RETURN;
+ }
+ case HA_ERR_WRONG_COMMAND:
+ my_error(ER_ILLEGAL_HA, MYF(0), "SEQUENCE", sequence_db, sequence_name);
+ DBUG_VOID_RETURN;
+ case ER_WRONG_INSERT_INTO_SEQUENCE:
+ my_error(error, MYF(0));
+ DBUG_VOID_RETURN;
+ }
+ file->print_error(error, errflag);
+ DBUG_VOID_RETURN;
+}
+
+/*****************************************************************************
+ Sequence plugin interface
+*****************************************************************************/
+
+/*
+ Create an new handler
+*/
+
+static handler *sequence_create_handler(handlerton *hton,
+ TABLE_SHARE *share,
+ MEM_ROOT *mem_root)
+{
+ DBUG_ENTER("sequence_create_handler");
+ DBUG_RETURN(new (mem_root) ha_sequence(hton, share));
+}
+
+
+/*
+ Sequence engine end.
+
+ SYNOPSIS
+ sequence_end()
+ p handlerton.
+ type panic type.
+ RETURN VALUES
+ 0 Success
+ !=0 Failure
+*/
+static int sequence_end(handlerton* hton,
+ ha_panic_function type __attribute__((unused)))
+{
+ DBUG_ENTER("sequence_end");
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Sequence engine init.
+
+ SYNOPSIS
+ sequence_initialize()
+
+ @param p handlerton.
+
+ retval 0 Success
+ retval !=0 Failure
+*/
+
+static int sequence_initialize(void *p)
+{
+ handlerton *local_sequence_hton= (handlerton *)p;
+ DBUG_ENTER("sequence_initialize");
+
+ local_sequence_hton->state= SHOW_OPTION_YES;
+ local_sequence_hton->db_type= DB_TYPE_SEQUENCE;
+ local_sequence_hton->create= sequence_create_handler;
+ local_sequence_hton->panic= sequence_end;
+ local_sequence_hton->flags= (HTON_NOT_USER_SELECTABLE |
+ HTON_HIDDEN |
+ HTON_TEMPORARY_NOT_SUPPORTED |
+ HTON_ALTER_NOT_SUPPORTED |
+ HTON_NO_PARTITION);
+ DBUG_RETURN(0);
+}
+
+
+static struct st_mysql_storage_engine sequence_storage_engine=
+{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+
+maria_declare_plugin(sql_sequence)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &sequence_storage_engine,
+ "SQL_SEQUENCE",
+ "jianwei.zhao @ Aliyun & Monty @ MariaDB corp",
+ "Sequence Storage Engine for CREATE SEQUENCE",
+ PLUGIN_LICENSE_GPL,
+ sequence_initialize, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ NULL, /* status variables */
+ NULL, /* system variables */
+ "1.0", /* string version */
+ MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */
+}
+maria_declare_plugin_end;
diff --git a/sql/ha_sequence.h b/sql/ha_sequence.h
new file mode 100644
index 00000000000..fd9da05b591
--- /dev/null
+++ b/sql/ha_sequence.h
@@ -0,0 +1,165 @@
+#ifndef HA_SEQUENCE_INCLUDED
+#define HA_SEQUENCE_INCLUDED
+/*
+ Copyright (c) 2017 Aliyun and/or its affiliates.
+ Copyright (c) 2017 MariaDB corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "sql_sequence.h"
+#include "table.h"
+#include "handler.h"
+
+extern handlerton *sql_sequence_hton;
+
+/*
+ Sequence engine handler.
+
+ The sequence engine is a logic engine. It doesn't store any data.
+ All the sequence data stored into the base table which must support
+ non rollback writes (HA_CAN_TABLES_WITHOUT_ROLLBACK)
+
+ The sequence data (SEQUENCE class) is stored in TABLE_SHARE->sequence
+
+ TABLE RULES:
+ 1. When table is created, one row is automaticlly inserted into
+ the table. The table will always have one and only one row.
+ 2. Any inserts or updates to the table will be validated.
+ 3. Inserts will overwrite the original row.
+ 4. DELETE and TRUNCATE will not affect the table.
+ Instead a warning will be given.
+ 5. Cache will be reset for any updates.
+
+ CACHE RULES:
+ SEQUENCE class is used to cache values that sequence defined.
+ 1. If hit cache, we can query back the sequence nextval directly
+ instead of reading the underlying table.
+
+ 2. When run out of values, the sequence engine will reserve new values
+ in update the base table.
+
+ 3. The cache is invalidated if any update on based table.
+*/
+
+class ha_sequence :public handler
+{
+private:
+ handler *file;
+ SEQUENCE *sequence; /* From table_share->sequence */
+
+public:
+ /* Set when handler is write locked */
+ bool write_locked;
+
+ ha_sequence(handlerton *hton, TABLE_SHARE *share);
+ ~ha_sequence();
+
+ /* virtual function that are re-implemented for sequence */
+ int open(const char *name, int mode, uint test_if_locked);
+ int create(const char *name, TABLE *form,
+ HA_CREATE_INFO *create_info);
+ handler *clone(const char *name, MEM_ROOT *mem_root);
+ int write_row(uchar *buf);
+ Table_flags table_flags() const;
+ /* One can't update or delete from sequence engine */
+ int update_row(const uchar *old_data, const uchar *new_data)
+ { return HA_ERR_WRONG_COMMAND; }
+ int delete_row(const uchar *buf)
+ { return HA_ERR_WRONG_COMMAND; }
+ /* One can't delete from sequence engine */
+ int truncate()
+ { return HA_ERR_WRONG_COMMAND; }
+ /* Can't use query cache */
+ uint8 table_cache_type()
+ { return HA_CACHE_TBL_NOCACHE; }
+ void print_error(int error, myf errflag);
+ int info(uint);
+ LEX_CSTRING *engine_name() { return hton_name(file->ht); }
+ int external_lock(THD *thd, int lock_type);
+ int extra(enum ha_extra_function operation);
+ /* For ALTER ONLINE TABLE */
+ bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
+ uint table_changes);
+ void write_lock() { write_locked= 1;}
+ void unlock() { write_locked= 0; }
+ bool is_locked() { return write_locked; }
+
+ /* Functions that are directly mapped to the underlying handler */
+ int rnd_init(bool scan)
+ { return file->rnd_init(scan); }
+ /*
+ We need to have a lock here to protect engines like MyISAM from
+ simultaneous read and write. For sequence's this is not critical
+ as this function is used extremely seldom.
+ */
+ int rnd_next(uchar *buf)
+ {
+ int error;
+ table->s->sequence->read_lock(table);
+ error= file->rnd_next(buf);
+ table->s->sequence->read_unlock(table);
+ return error;
+ }
+ int rnd_end()
+ { return file->rnd_end(); }
+ int rnd_pos(uchar *buf, uchar *pos)
+ {
+ int error;
+ table->s->sequence->read_lock(table);
+ error= file->rnd_pos(buf, pos);
+ table->s->sequence->read_unlock(table);
+ return error;
+ }
+ void position(const uchar *record)
+ { return file->position(record); }
+ const char *table_type() const
+ { return file->table_type(); }
+ ulong index_flags(uint inx, uint part, bool all_parts) const
+ { return file->index_flags(inx, part, all_parts); }
+ THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+ { return file->store_lock(thd, to, lock_type); }
+ int close(void)
+ { return file->close(); }
+ const char **bas_ext() const
+ { return file->bas_ext(); }
+ int delete_table(const char*name)
+ { return file->delete_table(name); }
+ int rename_table(const char *from, const char *to)
+ { return file->rename_table(from, to); }
+ void unbind_psi()
+ { return file->unbind_psi(); }
+ void rebind_psi()
+ { return file->rebind_psi(); }
+
+ bool auto_repair(int error) const
+ { return file->auto_repair(error); }
+ int repair(THD* thd, HA_CHECK_OPT* check_opt)
+ { return file->repair(thd, check_opt); }
+ bool check_and_repair(THD *thd)
+ { return file->check_and_repair(thd); }
+ bool is_crashed() const
+ { return file->is_crashed(); }
+ void column_bitmaps_signal()
+ { return file->column_bitmaps_signal(); }
+
+ /* New methods */
+ void register_original_handler(handler *file_arg)
+ {
+ file= file_arg;
+ init(); /* Update cached_table_flags */
+ }
+};
+#endif
diff --git a/sql/handler.cc b/sql/handler.cc
index a4a2297bd2f..4a9df5b2bf8 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -41,6 +41,7 @@
#include <mysql/psi/mysql_table.h>
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_audit.h"
+#include "ha_sequence.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -75,12 +76,12 @@ ulong total_ha_2pc= 0;
/* size of savepoint storage area (see ha_init) */
ulong savepoint_alloc_size= 0;
-static const LEX_STRING sys_table_aliases[]=
+static const LEX_CSTRING sys_table_aliases[]=
{
- { C_STRING_WITH_LEN("INNOBASE") }, { C_STRING_WITH_LEN("INNODB") },
- { C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
- { C_STRING_WITH_LEN("MERGE") }, { C_STRING_WITH_LEN("MRG_MYISAM") },
- { C_STRING_WITH_LEN("Maria") }, { C_STRING_WITH_LEN("Aria") },
+ { STRING_WITH_LEN("INNOBASE") }, { STRING_WITH_LEN("INNODB") },
+ { STRING_WITH_LEN("HEAP") }, { STRING_WITH_LEN("MEMORY") },
+ { STRING_WITH_LEN("MERGE") }, { STRING_WITH_LEN("MRG_MYISAM") },
+ { STRING_WITH_LEN("Maria") }, { STRING_WITH_LEN("Aria") },
{NullS, 0}
};
@@ -159,9 +160,10 @@ handlerton *ha_default_tmp_handlerton(THD *thd)
RETURN
pointer to storage engine plugin handle
*/
-plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name, bool tmp_table)
+plugin_ref ha_resolve_by_name(THD *thd, const LEX_CSTRING *name,
+ bool tmp_table)
{
- const LEX_STRING *table_alias;
+ const LEX_CSTRING *table_alias;
plugin_ref plugin;
redo:
@@ -291,7 +293,6 @@ handler *get_ha_partition(partition_info *part_info)
}
#endif
-
static const char **handler_errmsgs;
C_MODE_START
@@ -405,7 +406,7 @@ static int full_discover_for_existence(handlerton *, const char *, const char *)
static int ext_based_existence(handlerton *, const char *, const char *)
{ return 0; }
-static int hton_ext_based_table_discovery(handlerton *hton, LEX_STRING *db,
+static int hton_ext_based_table_discovery(handlerton *hton, LEX_CSTRING *db,
MY_DIR *dir, handlerton::discovered_list *result)
{
/*
@@ -618,7 +619,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
/*
This is entirely for legacy. We will create a new "disk based" hton and a
"memory" hton which will be configurable longterm. We should be able to
- remove partition and myisammrg.
+ remove partition.
*/
switch (hton->db_type) {
case DB_TYPE_HEAP:
@@ -630,6 +631,9 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
case DB_TYPE_PARTITION_DB:
partition_hton= hton;
break;
+ case DB_TYPE_SEQUENCE:
+ sql_sequence_hton= hton;
+ break;
default:
break;
};
@@ -2388,6 +2392,11 @@ err:
return NULL;
}
+LEX_CSTRING *handler::engine_name()
+{
+ return hton_name(ht);
+}
+
double handler::keyread_time(uint index, uint ranges, ha_rows rows)
{
@@ -2511,6 +2520,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
}
reset_statistics();
internal_tmp_table= MY_TEST(test_if_locked & HA_OPEN_INTERNAL_TABLE);
+
DBUG_RETURN(error);
}
@@ -2759,10 +2769,11 @@ int handler::ha_rnd_init_with_error(bool scan)
/**
- Read first row (only) from a table.
+ Read first row (only) from a table. Used for reading tables with
+ only one row, either based on table statistics or if table is a SEQUENCE.
- This is never called for InnoDB tables, as these table types
- has the HA_STATS_RECORDS_IS_EXACT set.
+ This is never called for normal InnoDB tables, as these table types
+ does not have HA_STATS_RECORDS_IS_EXACT set.
*/
int handler::read_first_row(uchar * buf, uint primary_key)
{
@@ -3553,7 +3564,7 @@ void handler::print_error(int error, myf errflag)
break;
case HA_ERR_AUTOINC_ERANGE:
textno= error;
- my_error(textno, errflag, table->next_number_field->field_name,
+ my_error(textno, errflag, table->next_number_field->field_name.str,
table->in_use->get_stmt_da()->current_row_for_warning());
DBUG_VOID_RETURN;
break;
@@ -3954,7 +3965,7 @@ void handler::mark_trx_read_write_internal()
*/
if (ha_info->is_started())
{
- DBUG_ASSERT(has_transactions());
+ DBUG_ASSERT(has_transaction_manager());
/*
table_share can be NULL in ha_delete_table(). See implementation
of standalone function ha_delete_table() in sql_base.cc.
@@ -3994,7 +4005,7 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
*/
int
-handler::ha_bulk_update_row(const uchar *old_data, uchar *new_data,
+handler::ha_bulk_update_row(const uchar *old_data, const uchar *new_data,
uint *dup_key_found)
{
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
@@ -5000,22 +5011,28 @@ private:
loaded, frm is invalid), the return value will be true, but
*hton will be NULL.
*/
+
bool ha_table_exists(THD *thd, const char *db, const char *table_name,
- handlerton **hton)
+ handlerton **hton, bool *is_sequence)
{
handlerton *dummy;
+ bool dummy2;
DBUG_ENTER("ha_table_exists");
if (hton)
*hton= 0;
else if (engines_with_discover)
hton= &dummy;
+ if (!is_sequence)
+ is_sequence= &dummy2;
+ *is_sequence= 0;
TDC_element *element= tdc_lock_share(thd, db, table_name);
if (element && element != MY_ERRPTR)
{
if (hton)
*hton= element->share->db_type();
+ *is_sequence= element->share->table_type == TABLE_TYPE_SEQUENCE;
tdc_unlock_share(element);
DBUG_RETURN(TRUE);
}
@@ -5031,11 +5048,12 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name,
if (hton)
{
char engine_buf[NAME_CHAR_LEN + 1];
- LEX_STRING engine= { engine_buf, 0 };
+ LEX_CSTRING engine= { engine_buf, 0 };
- if (dd_frm_type(thd, path, &engine) != FRMTYPE_VIEW)
+ if (dd_frm_type(thd, path, &engine, is_sequence) != TABLE_TYPE_VIEW)
{
- plugin_ref p= plugin_lock_by_name(thd, &engine, MYSQL_STORAGE_ENGINE_PLUGIN);
+ plugin_ref p= plugin_lock_by_name(thd, &engine,
+ MYSQL_STORAGE_ENGINE_PLUGIN);
*hton= p ? plugin_hton(p) : NULL;
if (*hton)
// verify that the table really exists
@@ -5056,7 +5074,6 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name,
DBUG_RETURN(TRUE);
}
-
if (need_full_discover_for_existence)
{
TABLE_LIST table;
@@ -5098,7 +5115,7 @@ static int cmp_file_names(const void *a, const void *b)
return my_strnncoll(cs, (uchar*)aa, strlen(aa), (uchar*)bb, strlen(bb));
}
-static int cmp_table_names(LEX_STRING * const *a, LEX_STRING * const *b)
+static int cmp_table_names(LEX_CSTRING * const *a, LEX_CSTRING * const *b)
{
return my_strnncoll(&my_charset_bin, (uchar*)((*a)->str), (*a)->length,
(uchar*)((*b)->str), (*b)->length);
@@ -5107,8 +5124,8 @@ static int cmp_table_names(LEX_STRING * const *a, LEX_STRING * const *b)
}
Discovered_table_list::Discovered_table_list(THD *thd_arg,
- Dynamic_array<LEX_STRING*> *tables_arg,
- const LEX_STRING *wild_arg) :
+ Dynamic_array<LEX_CSTRING*> *tables_arg,
+ const LEX_CSTRING *wild_arg) :
thd(thd_arg), with_temps(false), tables(tables_arg)
{
if (wild_arg->str && wild_arg->str[0])
@@ -5132,7 +5149,7 @@ bool Discovered_table_list::add_table(const char *tname, size_t tlen)
wild_prefix, wild_one, wild_many))
return 0;
- LEX_STRING *name= thd->make_lex_string(tname, tlen);
+ LEX_CSTRING *name= thd->make_clex_string(tname, tlen);
if (!name || tables->append(name))
return 1;
return 0;
@@ -5158,11 +5175,11 @@ void Discovered_table_list::sort()
void Discovered_table_list::remove_duplicates()
{
- LEX_STRING **src= tables->front();
- LEX_STRING **dst= src;
+ LEX_CSTRING **src= tables->front();
+ LEX_CSTRING **dst= src;
while (++dst <= tables->back())
{
- LEX_STRING *s= *src, *d= *dst;
+ LEX_CSTRING *s= *src, *d= *dst;
DBUG_ASSERT(strncmp(s->str, d->str, MY_MIN(s->length, d->length)) <= 0);
if ((s->length != d->length || strncmp(s->str, d->str, d->length)))
{
@@ -5176,7 +5193,7 @@ void Discovered_table_list::remove_duplicates()
struct st_discover_names_args
{
- LEX_STRING *db;
+ LEX_CSTRING *db;
MY_DIR *dirp;
Discovered_table_list *result;
uint possible_duplicates;
@@ -5221,7 +5238,7 @@ static my_bool discover_names(THD *thd, plugin_ref plugin,
for DROP DATABASE (as it needs to know and delete non-table files).
*/
-int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp,
+int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp,
Discovered_table_list *result, bool reusable)
{
int error;
@@ -5571,7 +5588,7 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
{
if (db_type->state != SHOW_OPTION_YES)
{
- const LEX_STRING *name= hton_name(db_type);
+ const LEX_CSTRING *name= hton_name(db_type);
result= stat_print(thd, name->str, name->length,
"", 0, "DISABLED", 8) ? 1 : 0;
}
@@ -5759,8 +5776,6 @@ static int write_locked_table_maps(THD *thd)
}
-typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
-
static int check_wsrep_max_ws_rows();
static int binlog_log_row_internal(TABLE* table,
@@ -5801,10 +5816,10 @@ static int binlog_log_row_internal(TABLE* table,
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
}
-static inline int binlog_log_row(TABLE* table,
- const uchar *before_record,
- const uchar *after_record,
- Log_func *log_func)
+int binlog_log_row(TABLE* table,
+ const uchar *before_record,
+ const uchar *after_record,
+ Log_func *log_func)
{
if (!table->file->check_table_binlog_row_based(1))
return 0;
@@ -5956,7 +5971,7 @@ int handler::ha_write_row(uchar *buf)
{ error= write_row(buf); })
MYSQL_INSERT_ROW_DONE(error);
- if (likely(!error))
+ if (likely(!error) && !row_already_logged)
{
rows_changed++;
error= binlog_log_row(table, 0, buf, log_func);
@@ -5966,7 +5981,7 @@ int handler::ha_write_row(uchar *buf)
}
-int handler::ha_update_row(const uchar *old_data, uchar *new_data)
+int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
{
int error;
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
@@ -5988,7 +6003,7 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
{ error= update_row(old_data, new_data);})
MYSQL_UPDATE_ROW_DONE(error);
- if (likely(!error))
+ if (likely(!error) && !row_already_logged)
{
rows_changed++;
error= binlog_log_row(table, old_data, new_data, log_func);
@@ -5996,6 +6011,34 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
return error;
}
+/*
+ Update first row. Only used by sequence tables
+*/
+
+int handler::update_first_row(uchar *new_data)
+{
+ int error;
+ if (!(error= ha_rnd_init(1)))
+ {
+ int end_error;
+ if (!(error= ha_rnd_next(table->record[1])))
+ {
+ /*
+ We have to do the memcmp as otherwise we may get error 169 from InnoDB
+ */
+ if (memcmp(table->record[0], table->record[1], table->s->reclength))
+ error= update_row(table->record[1], new_data);
+ }
+ end_error= ha_rnd_end();
+ if (!error)
+ error= end_error;
+ /* Logging would be wrong if update_row works but ha_rnd_end fails */
+ DBUG_ASSERT(!end_error || error != 0);
+ }
+ return error;
+}
+
+
int handler::ha_delete_row(const uchar *buf)
{
int error;
@@ -6443,7 +6486,7 @@ int del_global_index_stats_for_table(THD *thd, uchar* cache_key, uint cache_key_
/* Remove a table from global table statistics */
-int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table)
+int del_global_table_stat(THD *thd, LEX_CSTRING *db, LEX_CSTRING *table)
{
TABLE_STATS *table_stats;
int res = 0;
diff --git a/sql/handler.h b/sql/handler.h
index d021edf28d2..ac79c25746c 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -42,9 +42,11 @@
#include <ft_global.h>
#include <keycache.h>
#include <mysql/psi/mysql_table.h>
+#include "sql_sequence.h"
class Alter_info;
class Virtual_column_info;
+class sequence_definition;
// the following is for checking tables
@@ -262,6 +264,24 @@ enum enum_alter_inplace_result {
#define HA_CONCURRENT_OPTIMIZE (1ULL << 46)
/*
+ If the storage engine support tables that will not roll back on commit
+ In addition the table should not lock rows and support READ and WRITE
+ UNCOMMITTED.
+ This is useful for implementing things like SEQUENCE but can also in
+ the future be useful to do logging that should never roll back.
+*/
+#define HA_CAN_TABLES_WITHOUT_ROLLBACK (1ULL << 47)
+
+/*
+ Mainly for usage by SEQUENCE engine. Setting this flag means
+ that the table will never roll back and that all operations
+ for this table should stored in the non transactional log
+ space that will always be written, even on rollback.
+*/
+
+#define HA_PERSISTENT_TABLE (1ULL << 48)
+
+/*
Set of all binlog flags. Currently only contain the capabilities
flags.
*/
@@ -380,6 +400,7 @@ enum enum_alter_inplace_result {
#define HA_LEX_CREATE_TMP_TABLE 1U
#define HA_CREATE_TMP_ALTER 8U
+#define HA_LEX_CREATE_SEQUENCE 16U
#define HA_MAX_REC_LENGTH 65535
@@ -434,7 +455,8 @@ enum legacy_db_type
DB_TYPE_PERFORMANCE_SCHEMA=28,
DB_TYPE_ARIA=42,
DB_TYPE_TOKUDB=43,
- DB_TYPE_FIRST_DYNAMIC=44,
+ DB_TYPE_SEQUENCE=44,
+ DB_TYPE_FIRST_DYNAMIC=45,
DB_TYPE_DEFAULT=127 // Must be last
};
/*
@@ -522,6 +544,8 @@ given at all. */
*/
#define HA_CREATE_USED_STATS_SAMPLE_PAGES (1UL << 24)
+/* Create a sequence */
+#define HA_CREATE_USED_SEQUENCE (1UL << 25)
/*
This is master database for most of system tables. However there
@@ -1316,7 +1340,7 @@ struct handlerton
Returns 0 on success and 1 on error.
*/
- int (*discover_table_names)(handlerton *hton, LEX_STRING *db, MY_DIR *dir,
+ int (*discover_table_names)(handlerton *hton, LEX_CSTRING *db, MY_DIR *dir,
discovered_list *result);
/*
@@ -1362,7 +1386,7 @@ struct handlerton
};
-static inline LEX_STRING *hton_name(const handlerton *hton)
+static inline LEX_CSTRING *hton_name(const handlerton *hton)
{
return &(hton2plugin[hton->slot]->name);
}
@@ -1458,14 +1482,16 @@ struct THD_TRANS
unsigned int m_unsafe_rollback_flags;
/*
- Define the type of statemens which cannot be rolled back safely.
+ Define the type of statements which cannot be rolled back safely.
Each type occupies one bit in m_unsafe_rollback_flags.
*/
- static unsigned int const MODIFIED_NON_TRANS_TABLE= 0x01;
- static unsigned int const CREATED_TEMP_TABLE= 0x02;
- static unsigned int const DROPPED_TEMP_TABLE= 0x04;
- static unsigned int const DID_WAIT= 0x08;
- static unsigned int const DID_DDL= 0x10;
+ enum unsafe_statement_types
+ {
+ CREATED_TEMP_TABLE= 2,
+ DROPPED_TEMP_TABLE= 4,
+ DID_WAIT= 8,
+ DID_DDL= 0x10
+ };
void mark_created_temp_table()
{
@@ -1657,9 +1683,9 @@ struct Table_scope_and_contents_source_st
{
CHARSET_INFO *table_charset;
LEX_CUSTRING tabledef_version;
- LEX_STRING connect_string;
+ LEX_CSTRING connect_string;
+ LEX_CSTRING comment;
const char *password, *tablespace;
- LEX_STRING comment;
const char *data_file_name, *index_file_name;
const char *alias;
ulonglong max_rows,min_rows;
@@ -1697,6 +1723,7 @@ struct Table_scope_and_contents_source_st
engine_option_value *option_list; ///< list of table create options
enum_stats_auto_recalc stats_auto_recalc;
bool varchar; ///< 1 if table has a VARCHAR
+ bool sequence; // If SEQUENCE=1 was used
List<Virtual_column_info> *check_constraint_list;
@@ -1710,6 +1737,7 @@ struct Table_scope_and_contents_source_st
TABLE_LIST *pos_in_locked_tables;
MDL_ticket *mdl_ticket;
bool table_was_deleted;
+ sequence_definition *seq_create_info;
void init()
{
@@ -2152,8 +2180,8 @@ typedef struct st_key_create_information
{
enum ha_key_alg algorithm;
ulong block_size;
- LEX_STRING parser_name;
- LEX_STRING comment;
+ LEX_CSTRING parser_name;
+ LEX_CSTRING comment;
/**
A flag to determine if we will check for duplicate indexes.
This typically means that the key information was specified
@@ -2659,6 +2687,8 @@ public:
bool mark_trx_read_write_done; /* mark_trx_read_write was called */
bool check_table_binlog_row_based_done; /* check_table_binlog.. was called */
bool check_table_binlog_row_based_result; /* cached check_table_binlog... */
+ /* Set to 1 if handler logged last insert/update/delete operation */
+ bool row_already_logged;
/*
TRUE <=> the engine guarantees that returned records are within the range
being scanned.
@@ -2761,6 +2791,7 @@ public:
mark_trx_read_write_done(0),
check_table_binlog_row_based_done(0),
check_table_binlog_row_based_result(0),
+ row_already_logged(0),
in_range_check_pushed_down(FALSE),
key_used_on_scan(MAX_KEY),
active_index(MAX_KEY), keyread(MAX_KEY),
@@ -2864,7 +2895,7 @@ public:
*/
int ha_external_lock(THD *thd, int lock_type);
int ha_write_row(uchar * buf);
- int ha_update_row(const uchar * old_data, uchar * new_data);
+ int ha_update_row(const uchar * old_data, const uchar * new_data);
int ha_delete_row(const uchar * buf);
void ha_release_auto_increment();
@@ -2902,7 +2933,7 @@ public:
int ret= end_bulk_insert();
DBUG_RETURN(ret);
}
- int ha_bulk_update_row(const uchar *old_data, uchar *new_data,
+ int ha_bulk_update_row(const uchar *old_data, const uchar *new_data,
uint *dup_key_found);
int ha_delete_all_rows();
int ha_truncate();
@@ -2997,8 +3028,24 @@ public:
virtual double keyread_time(uint index, uint ranges, ha_rows rows);
virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
+
+ /*
+ True if changes to the table is persistent (no rollback)
+ This is manly used to decide how to log changes to the table in
+ the binary log.
+ */
bool has_transactions()
- { return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; }
+ {
+ return ((ha_table_flags() & (HA_NO_TRANSACTIONS | HA_PERSISTENT_TABLE))
+ == 0);
+ }
+ /*
+ True if the underlaying table doesn't support transactions
+ */
+ bool has_transaction_manager()
+ {
+ return ((ha_table_flags() & HA_NO_TRANSACTIONS) == 0);
+ }
/**
This method is used to analyse the error to see whether the error
@@ -3488,7 +3535,7 @@ public:
cached
*/
- virtual my_bool register_query_cache_table(THD *thd, char *table_key,
+ virtual my_bool register_query_cache_table(THD *thd, const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
@@ -3917,7 +3964,7 @@ public:
return 0;
}
- LEX_STRING *engine_name() { return hton_name(ht); }
+ virtual LEX_CSTRING *engine_name();
TABLE* get_table() { return table; }
TABLE_SHARE* get_table_share() { return table_share; }
@@ -4004,11 +4051,17 @@ private:
message will contain garbage.
*/
virtual int update_row(const uchar *old_data __attribute__((unused)),
- uchar *new_data __attribute__((unused)))
+ const uchar *new_data __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
}
+ /*
+ Optimized function for updating the first row. Only used by sequence
+ tables
+ */
+ virtual int update_first_row(uchar *new_data);
+
virtual int delete_row(const uchar *buf __attribute__((unused)))
{
return HA_ERR_WRONG_COMMAND;
@@ -4071,6 +4124,7 @@ protected:
enum ha_rkey_function find_flag)
{ return HA_ERR_WRONG_COMMAND; }
friend class ha_partition;
+ friend class ha_sequence;
public:
/**
This method is similar to update_row, however the handler doesn't need
@@ -4085,7 +4139,7 @@ public:
@retval 0 Bulk delete used by handler
@retval 1 Bulk delete not used, normal operation used
*/
- virtual int bulk_update_row(const uchar *old_data, uchar *new_data,
+ virtual int bulk_update_row(const uchar *old_data, const uchar *new_data,
uint *dup_key_found)
{
DBUG_ASSERT(FALSE);
@@ -4171,11 +4225,27 @@ public:
virtual handlerton *partition_ht() const
{ return ht; }
inline int ha_write_tmp_row(uchar *buf);
+ inline int ha_delete_tmp_row(uchar *buf);
inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data);
virtual void set_lock_type(enum thr_lock_type lock);
friend enum icp_result handler_index_cond_check(void* h_arg);
+
+ /**
+ Find unique record by index or unique constrain
+
+ @param record record to find (also will be fillded with
+ actual record fields)
+ @param unique_ref index or unique constraiun number (depends
+ on what used in the engine
+
+ @retval -1 Error
+ @retval 1 Not found
+ @retval 0 Found
+ */
+ virtual int find_unique_row(uchar *record, uint unique_ref)
+ { return -1; /*unsupported */}
protected:
Handler_share *get_ha_share_ptr();
void set_ha_share_ptr(Handler_share *arg_ha_share);
@@ -4198,7 +4268,7 @@ extern const char *myisam_stats_method_names[];
extern ulong total_ha, total_ha_2pc;
/* lookups */
-plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name, bool tmp_table);
+plugin_ref ha_resolve_by_name(THD *thd, const LEX_CSTRING *name, bool tmp_table);
plugin_ref ha_lock_engine(THD *thd, const handlerton *hton);
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type);
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
@@ -4266,11 +4336,11 @@ class Discovered_table_list: public handlerton::discovered_list
const char *wild, *wend;
bool with_temps; // whether to include temp tables in the result
public:
- Dynamic_array<LEX_STRING*> *tables;
+ Dynamic_array<LEX_CSTRING*> *tables;
- Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_STRING*> *tables_arg,
- const LEX_STRING *wild_arg);
- Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_STRING*> *tables_arg)
+ Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_CSTRING*> *tables_arg,
+ const LEX_CSTRING *wild_arg);
+ Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_CSTRING*> *tables_arg)
: thd(thd_arg), wild(NULL), with_temps(true), tables(tables_arg) {}
~Discovered_table_list() {}
@@ -4282,10 +4352,10 @@ public:
};
int ha_discover_table(THD *thd, TABLE_SHARE *share);
-int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp,
+int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp,
Discovered_table_list *result, bool reusable);
bool ha_table_exists(THD *thd, const char *db, const char *table_name,
- handlerton **hton= 0);
+ handlerton **hton= 0, bool *is_sequence= 0);
#endif
/* key cache */
@@ -4340,6 +4410,11 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
}
+typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
+int binlog_log_row(TABLE* table,
+ const uchar *before_record,
+ const uchar *after_record,
+ Log_func *log_func);
#define TABLE_IO_WAIT(TRACKER, PSI, OP, INDEX, FLAGS, PAYLOAD) \
{ \
@@ -4357,5 +4432,5 @@ void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
void print_keydup_error(TABLE *table, KEY *key, myf errflag);
int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info);
-int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table);
+int del_global_table_stat(THD *thd, LEX_CSTRING *db, LEX_CSTRING *table);
#endif /* HANDLER_INCLUDED */
diff --git a/sql/item.cc b/sql/item.cc
index 6d999daf801..7d3f8788c3f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -45,6 +45,15 @@
const String my_null_string("NULL", 4, default_charset_info);
const String my_default_string("DEFAULT", 7, default_charset_info);
+/*
+ item_empty_name is used when calling Item::set_name with NULL
+ pointer, to make it easier to use the name in printf.
+ item_used_name is used when calling Item::set_name with a 0 length
+ string.
+*/
+const char *item_empty_name="";
+const char *item_used_name= "\0";
+
static int save_field_in_field(Field *, bool *, Field *, bool);
@@ -302,6 +311,56 @@ bool Item::is_null_from_temporal()
}
+longlong Item::val_int_from_str(int *error)
+{
+ char buff[MAX_FIELD_WIDTH];
+ String tmp(buff,sizeof(buff), &my_charset_bin), *res;
+
+ /*
+ For a string result, we must first get the string and then convert it
+ to a longlong
+ */
+ if (!(res= val_str(&tmp)))
+ {
+ *error= 0;
+ return 0;
+ }
+ Converter_strtoll10_with_warn cnv(NULL, Warn_filter_all(),
+ res->charset(), res->ptr(), res->length());
+ *error= cnv.error();
+ return cnv.result();
+}
+
+
+longlong Item::val_int_signed_typecast_from_str()
+{
+ int error;
+ longlong value= val_int_from_str(&error);
+ if (!null_value && value < 0 && error == 0)
+ push_note_converted_to_negative_complement(current_thd);
+ return value;
+}
+
+
+longlong Item::val_int_unsigned_typecast_from_str()
+{
+ int error;
+ longlong value= val_int_from_str(&error);
+ if (!null_value && error < 0)
+ push_note_converted_to_positive_complement(current_thd);
+ return value;
+}
+
+
+longlong Item::val_int_unsigned_typecast_from_int()
+{
+ longlong value= val_int();
+ if (!null_value && unsigned_flag == 0 && value < 0)
+ push_note_converted_to_positive_complement(current_thd);
+ return value;
+}
+
+
String *Item::val_string_from_date(String *str)
{
MYSQL_TIME ltime;
@@ -419,21 +478,33 @@ longlong Item::val_int_from_decimal()
return result;
}
-int Item::save_time_in_field(Field *field)
+
+longlong Item::val_int_unsigned_typecast_from_decimal()
+{
+ longlong result;
+ my_decimal tmp, *dec= val_decimal(&tmp);
+ if (null_value)
+ return 0;
+ my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &result);
+ return result;
+}
+
+
+int Item::save_time_in_field(Field *field, bool no_conversions)
{
MYSQL_TIME ltime;
if (get_time(&ltime))
- return set_field_to_null_with_conversions(field, 0);
+ return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
return field->store_time_dec(&ltime, decimals);
}
-int Item::save_date_in_field(Field *field)
+int Item::save_date_in_field(Field *field, bool no_conversions)
{
MYSQL_TIME ltime;
if (get_date(&ltime, sql_mode_for_dates(field->table->in_use)))
- return set_field_to_null_with_conversions(field, 0);
+ return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
return field->store_time_dec(&ltime, decimals);
}
@@ -471,7 +542,7 @@ int Item::save_str_value_in_field(Field *field, String *result)
Item::Item(THD *thd):
- is_expensive_cache(-1), rsize(0), name(0), orig_name(0), name_length(0),
+ is_expensive_cache(-1), rsize(0), name(null_clex_str), orig_name(0),
fixed(0), is_autogenerated_name(TRUE)
{
DBUG_ASSERT(thd);
@@ -508,14 +579,13 @@ Item::Item(THD *thd):
tables.
*/
Item::Item(THD *thd, Item *item):
- Type_std_attributes(item),
+ Type_all_attributes(item),
join_tab_idx(item->join_tab_idx),
is_expensive_cache(-1),
rsize(0),
str_value(item->str_value),
name(item->name),
orig_name(item->orig_name),
- name_length(item->name_length),
marker(item->marker),
maybe_null(item->maybe_null),
in_rollup(item->in_rollup),
@@ -532,49 +602,6 @@ Item::Item(THD *thd, Item *item):
}
-uint Item::decimal_precision() const
-{
- Item_result restype= result_type();
-
- if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT))
- {
- uint prec=
- my_decimal_length_to_precision(max_char_length(), decimals,
- unsigned_flag);
- return MY_MIN(prec, DECIMAL_MAX_PRECISION);
- }
- uint res= max_char_length();
- /*
- Return at least one decimal digit, even if Item::max_char_length()
- returned 0. This is important to avoid attempts to create fields of types
- INT(0) or DECIMAL(0,0) when converting NULL or empty strings to INT/DECIMAL:
- CREATE TABLE t1 AS SELECT CONVERT(NULL,SIGNED) AS a;
- */
- return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
-}
-
-
-uint Item::temporal_precision(enum_field_types type_arg)
-{
- if (const_item() && result_type() == STRING_RESULT &&
- !is_temporal_type(field_type()))
- {
- MYSQL_TIME ltime;
- String buf, *tmp;
- MYSQL_TIME_STATUS status;
- DBUG_ASSERT(fixed);
- if ((tmp= val_str(&buf)) &&
- !(type_arg == MYSQL_TYPE_TIME ?
- str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
- &ltime, TIME_TIME_ONLY, &status) :
- str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
- &ltime, TIME_FUZZY_DATES, &status)))
- return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
- }
- return MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
-}
-
-
void Item::print_parenthesised(String *str, enum_query_type query_type,
enum precedence parent_prec)
{
@@ -597,11 +624,12 @@ void Item::print_item_w_name(String *str, enum_query_type query_type)
{
print(str, query_type);
- if (name)
+ if (name.str)
{
+ DBUG_ASSERT(name.length == strlen(name.str));
THD *thd= current_thd;
str->append(STRING_WITH_LEN(" AS "));
- append_identifier(thd, str, name, (uint) strlen(name));
+ append_identifier(thd, str, name.str, name.length);
}
}
@@ -640,7 +668,10 @@ void Item::cleanup()
marker= 0;
join_tab_idx= MAX_TABLES;
if (orig_name)
- name= orig_name;
+ {
+ name.str= orig_name;
+ name.length= strlen(orig_name);
+ }
DBUG_VOID_RETURN;
}
@@ -660,24 +691,6 @@ bool Item::cleanup_processor(void *arg)
/**
- rename item (used for views, cleanup() return original name).
-
- @param new_name new name of item;
-*/
-
-void Item::rename(char *new_name)
-{
- /*
- we can compare pointers to names here, because if name was not changed,
- pointer will be same
- */
- if (!orig_name && new_name != name)
- orig_name= name;
- name= new_name;
-}
-
-
-/**
Traverse item tree possibly transforming it (replacing items).
This function is designed to ease transformation of Item trees.
@@ -746,29 +759,31 @@ Item* Item::set_expr_cache(THD *thd)
Item_ident::Item_ident(THD *thd, Name_resolution_context *context_arg,
const char *db_name_arg,const char *table_name_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Item_result_field(thd), orig_db_name(db_name_arg),
orig_table_name(table_name_arg),
- orig_field_name(field_name_arg), context(context_arg),
+ orig_field_name(*field_name_arg), context(context_arg),
db_name(db_name_arg), table_name(table_name_arg),
- field_name(field_name_arg),
+ field_name(*field_name_arg),
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
cached_table(0), depended_from(0), can_be_depended(TRUE)
{
- name = (char*) field_name_arg;
+ name= *field_name_arg;
}
-Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_arg)
+Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg,
+ const LEX_CSTRING *field_name_arg)
:Item_result_field(thd), orig_db_name(NullS),
orig_table_name(view_arg->table_name),
- orig_field_name(field_name_arg), context(&view_arg->view->select_lex.context),
+ orig_field_name(*field_name_arg),
+ context(&view_arg->view->select_lex.context),
db_name(NullS), table_name(view_arg->alias),
- field_name(field_name_arg),
+ field_name(*field_name_arg),
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
cached_table(NULL), depended_from(NULL), can_be_depended(TRUE)
{
- name = (char*) field_name_arg;
+ name= *field_name_arg;
}
@@ -859,7 +874,8 @@ bool Item_ident::collect_outer_ref_processor(void *param)
bool Item_field::collect_item_field_processor(void *arg)
{
DBUG_ENTER("Item_field::collect_item_field_processor");
- DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname"));
+ DBUG_PRINT("info", ("%s", field->field_name.str ?
+ field->field_name.str : "noname"));
List<Item_field> *item_list= (List<Item_field>*) arg;
List_iterator<Item_field> item_list_it(*item_list);
Item_field *curr_item;
@@ -876,7 +892,8 @@ bool Item_field::collect_item_field_processor(void *arg)
bool Item_field::add_field_to_set_processor(void *arg)
{
DBUG_ENTER("Item_field::add_field_to_set_processor");
- DBUG_PRINT("info", ("%s", field->field_name ? field->field_name : "noname"));
+ DBUG_PRINT("info", ("%s", field->field_name.str ? field->field_name.str :
+ "noname"));
TABLE *table= (TABLE *) arg;
if (field->table == table)
bitmap_set_bit(&table->tmp_set, field->field_index);
@@ -1004,7 +1021,7 @@ bool Item_field::check_field_expression_processor(void *arg)
{
my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD,
MYF(0),
- org_field->field_name, field->field_name);
+ org_field->field_name.str, field->field_name.str);
return 1;
}
}
@@ -1035,13 +1052,86 @@ bool Item::check_cols(uint c)
}
+bool Item::check_type_or_binary(const char *opname,
+ const Type_handler *expect) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler == expect ||
+ (handler->is_general_purpose_string_type() &&
+ collation.collation == &my_charset_bin))
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_general_purpose_string(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->is_general_purpose_string_type())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_traditional_scalar(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->is_traditional_type() && handler->is_scalar_type())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_can_return_int(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->can_return_int())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_can_return_real(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->can_return_real())
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ handler->name().ptr(), opname);
+ return true;
+}
+
+
+bool Item::check_type_scalar(const char *opname) const
+{
+ const Type_handler *handler= type_handler();
+ if (handler->is_scalar_type())
+ return false;
+ my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
+ return true;
+}
+
+
void Item::set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs)
{
if (!length)
{
- /* Empty string, used by AS or internal function like last_insert_id() */
- name= (char*) str;
- name_length= 0;
+ /*
+ Null string are replaced by item_empty_name. This is used by AS or
+ internal function like last_insert_id() to detect if we need to
+ change the name later.
+ Used by sql_yacc.yy in select_alias handling
+ */
+ name.str= str ? item_used_name : item_empty_name;
+ name.length= 0;
return;
}
@@ -1083,13 +1173,13 @@ void Item::set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs)
if (!my_charset_same(cs, system_charset_info))
{
size_t res_length;
- name= sql_strmake_with_convert(thd, str, length, cs,
- MAX_ALIAS_NAME, system_charset_info,
- &res_length);
- name_length= res_length;
+ name.str= sql_strmake_with_convert(thd, str, length, cs,
+ MAX_ALIAS_NAME, system_charset_info,
+ &res_length);
+ name.length= res_length;
}
else
- name= thd->strmake(str, (name_length= MY_MIN(length,MAX_ALIAS_NAME)));
+ name.str= thd->strmake(str, (name.length= MY_MIN(length,MAX_ALIAS_NAME)));
}
@@ -1099,28 +1189,13 @@ void Item::set_name_no_truncate(THD *thd, const char *str, uint length,
if (!my_charset_same(cs, system_charset_info))
{
size_t res_length;
- name= sql_strmake_with_convert(thd, str, length, cs,
- UINT_MAX, system_charset_info,
- &res_length);
- name_length= res_length;
+ name.str= sql_strmake_with_convert(thd, str, length, cs,
+ UINT_MAX, system_charset_info,
+ &res_length);
+ name.length= res_length;
}
else
- name= thd->strmake(str, (name_length= length));
-}
-
-
-void Item::set_name_for_rollback(THD *thd, const char *str, uint length,
- CHARSET_INFO *cs)
-{
- char *old_name, *new_name;
- old_name= name;
- set_name(thd, str, length, cs);
- new_name= name;
- if (old_name != new_name)
- {
- name= old_name;
- thd->change_item_tree((Item **) &name, (Item *) new_name);
- }
+ name.str= thd->strmake(str, (name.length= length));
}
@@ -1138,8 +1213,9 @@ bool Item::eq(const Item *item, bool binary_cmp) const
for all basic constants we have special checks, and Item_param's
type() can be only among basic constant types.
*/
- return type() == item->type() && name && item->name &&
- !my_strcasecmp(system_charset_info,name,item->name);
+ return type() == item->type() && name.str && item->name.str &&
+ name.length == item->name.length &&
+ !my_strcasecmp(system_charset_info, name.str, item->name.str);
}
@@ -1481,24 +1557,18 @@ bool mark_unsupported_function(const char *w1, const char *w2,
Item_sp_variable methods
*****************************************************************************/
-Item_sp_variable::Item_sp_variable(THD *thd, char *sp_var_name_str,
- uint sp_var_name_length):
- Item(thd), m_thd(0)
+Item_sp_variable::Item_sp_variable(THD *thd, const LEX_CSTRING *sp_var_name)
+ :Item(thd), m_thd(0), m_name(*sp_var_name)
#ifndef DBUG_OFF
, m_sp(0)
#endif
{
- m_name.str= sp_var_name_str;
- m_name.length= sp_var_name_length;
}
-bool Item_sp_variable::fix_fields(THD *thd, Item **)
+bool Item_sp_variable::fix_fields_from_item(THD *thd, Item **, const Item *it)
{
- Item *it;
-
m_thd= thd; /* NOTE: this must be set before any this_xxx() */
- it= this_item();
DBUG_ASSERT(it->fixed);
@@ -1583,16 +1653,26 @@ bool Item_sp_variable::is_null()
return this_item()->is_null();
}
+void Item_sp_variable::make_field(THD *thd, Send_field *field)
+{
+ Item *it= this_item();
+
+ it->make_field(thd, field);
+ if (name.str)
+ field->col_name= name;
+ else
+ field->col_name= m_name;
+}
/*****************************************************************************
Item_splocal methods
*****************************************************************************/
-Item_splocal::Item_splocal(THD *thd, const LEX_STRING &sp_var_name,
+Item_splocal::Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name,
uint sp_var_idx,
enum_field_types sp_var_type,
uint pos_in_q, uint len_in_q):
- Item_sp_variable(thd, sp_var_name.str, sp_var_name.length),
+ Item_sp_variable(thd, sp_var_name),
Rewritable_query_parameter(pos_in_q, len_in_q),
m_var_idx(sp_var_idx)
{
@@ -1604,11 +1684,19 @@ Item_splocal::Item_splocal(THD *thd, const LEX_STRING &sp_var_name,
}
+bool Item_splocal::fix_fields(THD *thd, Item **ref)
+{
+ Item *item= thd->spcont->get_item(m_var_idx);
+ set_handler(item->type_handler());
+ return fix_fields_from_item(thd, ref, item);
+}
+
+
Item *
Item_splocal::this_item()
{
DBUG_ASSERT(m_sp == m_thd->spcont->sp);
-
+ DBUG_ASSERT(fixed);
return m_thd->spcont->get_item(m_var_idx);
}
@@ -1616,7 +1704,7 @@ const Item *
Item_splocal::this_item() const
{
DBUG_ASSERT(m_sp == m_thd->spcont->sp);
-
+ DBUG_ASSERT(fixed);
return m_thd->spcont->get_item(m_var_idx);
}
@@ -1625,7 +1713,7 @@ Item **
Item_splocal::this_item_addr(THD *thd, Item **)
{
DBUG_ASSERT(m_sp == thd->spcont->sp);
-
+ DBUG_ASSERT(fixed);
return thd->spcont->get_item_addr(m_var_idx);
}
@@ -1645,17 +1733,195 @@ bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
}
+/**
+ These two declarations are different:
+ x INT;
+ ROW(x INT);
+ A ROW with one elements should not be comparable to scalar value.
+
+ TODO: Currently we don't support one argument with the function ROW(), so
+ this query returns a syntax error, meaning that more arguments are expected:
+ SELECT ROW(1);
+
+ Therefore, all around the code we assume that cols()==1 means a scalar value
+ and cols()>1 means a ROW value. With adding ROW SP variables this
+ assumption is not true any more. ROW variables with one element are
+ now possible.
+
+ To implement Item::check_cols() correctly, we now should extend it to
+ know if a ROW or a scalar value is being tested. For example,
+ these new prototypes should work:
+ virtual bool check_cols(Item_result result, uint c);
+ or
+ virtual bool check_cols(const Type_handler *type, uint c);
+
+ The current implementation of Item_splocal::check_cols() is a compromise
+ that should be more or less fine until we extend check_cols().
+ It disallows ROW variables to appear in a scalar context.
+ The "|| n == 1" part of the conditon is responsible for this.
+ For example, it disallows ROW variables to appear in SELECT list:
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+
+ But is produces false negatives with ROW variables consisting of one element.
+ For example, this script fails:
+
+SET sql_mode=ORACLE;
+DROP PROCEDURE IF EXISTS p1;
+DELIMITER $$
+CREATE PROCEDURE p1
+AS
+ a ROW(a INT);
+ b ROW(a INT);
+BEGIN
+ SELECT a=b;
+END;
+$$
+DELIMITER ;
+CALL p1();
+
+ and returns "ERROR 1241 (21000): Operand should contain 1 column(s)".
+ This will be fixed that we change check_cols().
+*/
+
+bool Item_splocal::check_cols(uint n)
+{
+ DBUG_ASSERT(m_thd->spcont);
+ if (Type_handler_hybrid_field_type::cmp_type() != ROW_RESULT)
+ return Item::check_cols(n);
+
+ if (n != this_item()->cols() || n == 1)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), n);
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_splocal_row_field::fix_fields(THD *thd, Item **ref)
+{
+ Item *item= thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
+ return fix_fields_from_item(thd, ref, item);
+}
+
+
+Item *
+Item_splocal_row_field::this_item()
+{
+ DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(fixed);
+ return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
+}
+
+
+const Item *
+Item_splocal_row_field::this_item() const
+{
+ DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(fixed);
+ return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
+}
+
+
+Item **
+Item_splocal_row_field::this_item_addr(THD *thd, Item **)
+{
+ DBUG_ASSERT(m_sp == thd->spcont->sp);
+ DBUG_ASSERT(fixed);
+ return thd->spcont->get_item(m_var_idx)->addr(m_field_idx);
+}
+
+
+void Item_splocal_row_field::print(String *str, enum_query_type)
+{
+ str->reserve(m_name.length + m_field_name.length + 8);
+ str->append(m_name.str, m_name.length);
+ str->append('.');
+ str->append(m_field_name.str, m_field_name.length);
+ str->append('@');
+ str->qs_append(m_var_idx);
+ str->append('[');
+ str->qs_append(m_field_idx);
+ str->append(']');
+}
+
+
+bool Item_splocal_row_field::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ return ctx->set_variable_row_field(thd, m_var_idx, m_field_idx, it);
+}
+
+
+bool Item_splocal_row_field_by_name::fix_fields(THD *thd, Item **it)
+{
+ m_thd= thd;
+ Item *item, *row= m_thd->spcont->get_item(m_var_idx);
+ if (row->element_index_by_name(&m_field_idx, m_field_name))
+ {
+ my_error(ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD, MYF(0),
+ m_name.str, m_field_name.str);
+ return true;
+ }
+ item= row->element_index(m_field_idx);
+ set_handler(item->type_handler());
+ return fix_fields_from_item(thd, it, item);
+}
+
+
+void Item_splocal_row_field_by_name::print(String *str, enum_query_type)
+{
+ // +16 should be enough for .NNN@[""]
+ if (str->reserve(m_name.length + 2 * m_field_name.length + 16))
+ return;
+ str->qs_append(m_name.str, m_name.length);
+ str->qs_append('.');
+ str->qs_append(m_field_name.str, m_field_name.length);
+ str->qs_append('@');
+ str->qs_append(m_var_idx);
+ str->qs_append("[\"", 2);
+ str->qs_append(m_field_name.str, m_field_name.length);
+ str->qs_append("\"]", 2);
+}
+
+
+bool Item_splocal_row_field_by_name::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ DBUG_ASSERT(fixed); // Make sure m_field_idx is already set
+ return Item_splocal_row_field::set_value(thd, ctx, it);
+}
+
+
/*****************************************************************************
Item_case_expr methods
*****************************************************************************/
+LEX_CSTRING str_case_expr= { STRING_WITH_LEN("case_expr") };
+
Item_case_expr::Item_case_expr(THD *thd, uint case_expr_id):
- Item_sp_variable(thd, C_STRING_WITH_LEN("case_expr")),
+ Item_sp_variable(thd, &str_case_expr),
m_case_expr_id(case_expr_id)
{
}
+bool Item_case_expr::fix_fields(THD *thd, Item **ref)
+{
+ Item *item= thd->spcont->get_case_expr(m_case_expr_id);
+ return fix_fields_from_item(thd, ref, item);
+}
+
+
Item *
Item_case_expr::this_item()
{
@@ -1823,7 +2089,7 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref)
}
if (is_autogenerated_name)
{
- set_name(thd, item_name->ptr(), (uint) item_name->length(),
+ set_name(thd, item_name->c_ptr(), (uint) item_name->length(),
system_charset_info);
}
collation.set(value_item->collation.collation, DERIVATION_IMPLICIT);
@@ -1854,7 +2120,7 @@ class Item_aggregate_ref : public Item_ref
public:
Item_aggregate_ref(THD *thd, Name_resolution_context *context_arg,
Item **item, const char *table_name_arg,
- const char *field_name_arg):
+ const LEX_CSTRING *field_name_arg):
Item_ref(thd, context_arg, item, table_name_arg, field_name_arg) {}
virtual inline void print (String *str, enum_query_type query_type)
@@ -1971,14 +2237,14 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
already a reference.
*/
Item *real_itm= real_item();
-
ref_pointer_array[el]= real_itm;
if (type() == WINDOW_FUNC_ITEM)
{
if (!(item_ref= (new (thd->mem_root)
Item_direct_ref(thd,
- &thd->lex->current_select->context,
- &ref_pointer_array[el], 0, name))))
+ &thd->lex->current_select->context,
+ &ref_pointer_array[el], 0,
+ &name))))
return; // fatal_error is set
}
else
@@ -1986,7 +2252,8 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
if (!(item_ref= (new (thd->mem_root)
Item_aggregate_ref(thd,
&thd->lex->current_select->context,
- &ref_pointer_array[el], 0, name))))
+ &ref_pointer_array[el], 0,
+ &name))))
return; // fatal_error is set
}
if (type() == SUM_FUNC_ITEM)
@@ -2191,9 +2458,9 @@ void my_coll_agg_error(Item** args, uint count, const char *fname,
}
-bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
- Item **av, uint count,
- uint flags, int item_sep)
+bool Type_std_attributes::agg_item_collations(DTCollation &c, const char *fname,
+ Item **av, uint count,
+ uint flags, int item_sep)
{
uint i;
Item **arg;
@@ -2238,10 +2505,10 @@ bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
}
-bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll,
- const char *fname,
- Item **args, uint nargs,
- uint flags, int item_sep)
+bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
+ const char *fname,
+ Item **args, uint nargs,
+ uint flags, int item_sep)
{
Item **arg, *safe_args[2]= {NULL, NULL};
@@ -2400,7 +2667,6 @@ void Item_ident_for_show::make_field(THD *thd, Send_field *tmp_field)
tmp_field->table_name= tmp_field->org_table_name= table_name;
tmp_field->db_name= db_name;
tmp_field->col_name= tmp_field->org_col_name= field->field_name;
- tmp_field->charsetnr= field->charset()->number;
tmp_field->length=field->field_length;
tmp_field->type=field->type();
tmp_field->flags= field->table->maybe_null ?
@@ -2411,7 +2677,7 @@ void Item_ident_for_show::make_field(THD *thd, Send_field *tmp_field)
/**********************************************/
Item_field::Item_field(THD *thd, Field *f)
- :Item_ident(thd, 0, NullS, *f->table_name, f->field_name),
+ :Item_ident(thd, 0, NullS, *f->table_name, &f->field_name),
item_equal(0),
have_privileges(0), any_privileges(0)
{
@@ -2420,7 +2686,8 @@ Item_field::Item_field(THD *thd, Field *f)
field_name and table_name should not point to garbage
if this item is to be reused
*/
- orig_table_name= orig_field_name= "";
+ orig_table_name= "";
+ orig_field_name= null_clex_str;
with_field= 1;
}
@@ -2434,7 +2701,8 @@ Item_field::Item_field(THD *thd, Field *f)
Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
Field *f)
- :Item_ident(thd, context_arg, f->table->s->db.str, *f->table_name, f->field_name),
+ :Item_ident(thd, context_arg, f->table->s->db.str, *f->table_name,
+ &f->field_name),
item_equal(0),
have_privileges(0), any_privileges(0)
{
@@ -2460,14 +2728,15 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
orig_db_name= thd->strdup(db_name);
if (table_name)
orig_table_name= thd->strdup(table_name);
- if (field_name)
- orig_field_name= thd->strdup(field_name);
+ if (field_name.str)
+ thd->make_lex_string(&orig_field_name, field_name.str,
+ field_name.length);
/*
We don't restore 'name' in cleanup because it's not changed
during execution. Still we need it to point to persistent
memory if this item is to be reused.
*/
- name= (char*) orig_field_name;
+ name= orig_field_name;
}
set_field(f);
with_field= 1;
@@ -2476,7 +2745,7 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
const char *db_arg,const char *table_name_arg,
- const char *field_name_arg)
+ const LEX_CSTRING *field_name_arg)
:Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg),
field(0), item_equal(0),
have_privileges(0), any_privileges(0)
@@ -2562,15 +2831,11 @@ void Item_field::set_field(Field *field_par)
{
field=result_field=field_par; // for easy coding with fields
maybe_null=field->maybe_null();
- decimals= field->decimals();
+ Type_std_attributes::set(field_par);
table_name= *field_par->table_name;
field_name= field_par->field_name;
db_name= field_par->table->s->db.str;
alias_name_used= field_par->table->alias_name_used;
- unsigned_flag= MY_TEST(field_par->flags & UNSIGNED_FLAG);
- collation.set(field_par->charset(), field_par->derivation(),
- field_par->repertoire());
- fix_char_length(field_par->char_length());
max_length= adjust_max_effective_column_length(field_par, max_length);
@@ -2590,7 +2855,7 @@ void Item_field::reset_field(Field *f)
{
set_field(f);
/* 'name' is pointing at field->field_name of old field */
- name= (char*) f->field_name;
+ name= f->field_name;
}
@@ -2629,15 +2894,15 @@ bool Item_field::switch_to_nullable_fields_processor(void *arg)
const char *Item_ident::full_name() const
{
char *tmp;
- if (!table_name || !field_name)
- return field_name ? field_name : name ? name : "tmp_field";
+ if (!table_name || !field_name.str)
+ return field_name.str ? field_name.str : name.str ? name.str : "tmp_field";
if (db_name && db_name[0])
{
THD *thd= current_thd;
tmp=(char*) thd->alloc((uint) strlen(db_name)+(uint) strlen(table_name)+
- (uint) strlen(field_name)+3);
- strxmov(tmp,db_name,".",table_name,".",field_name,NullS);
+ (uint) field_name.length+3);
+ strxmov(tmp,db_name,".",table_name,".",field_name.str,NullS);
}
else
{
@@ -2645,11 +2910,11 @@ const char *Item_ident::full_name() const
{
THD *thd= current_thd;
tmp= (char*) thd->alloc((uint) strlen(table_name) +
- (uint) strlen(field_name) + 2);
- strxmov(tmp, table_name, ".", field_name, NullS);
+ field_name.length + 2);
+ strxmov(tmp, table_name, ".", field_name.str, NullS);
}
else
- tmp= (char*) field_name;
+ return field_name.str;
}
return tmp;
}
@@ -2686,7 +2951,7 @@ void Item_ident::print(String *str, enum_query_type query_type)
use_db_name= use_table_name= false;
}
- if (!field_name || !field_name[0])
+ if (!field_name.str || !field_name.str[0])
{
append_identifier(thd, str, STRING_WITH_LEN("tmp_field"));
return;
@@ -2720,7 +2985,7 @@ void Item_ident::print(String *str, enum_query_type query_type)
append_identifier(thd, str, t_name, (uint) strlen(t_name));
str->append('.');
}
- append_identifier(thd, str, field_name, (uint) strlen(field_name));
+ append_identifier(thd, str, field_name.str, field_name.length);
}
/* ARGSUSED */
@@ -2851,8 +3116,8 @@ bool Item_field::eq(const Item *item, bool binary_cmp) const
(In cases where we would choose wrong we would have to generate a
ER_NON_UNIQ_ERROR).
*/
- return (!my_strcasecmp(system_charset_info, item_field->name,
- field_name) &&
+ return (!my_strcasecmp(system_charset_info, item_field->name.str,
+ field_name.str) &&
(!item_field->table_name || !table_name ||
(!my_strcasecmp(table_alias_charset, item_field->table_name,
table_name) &&
@@ -2979,7 +3244,12 @@ Item_int::Item_int(THD *thd, const char *str_arg, uint length):
int error;
value= my_strtoll10(str_arg, &end_ptr, &error);
max_length= (uint) (end_ptr - str_arg);
- name= (char*) str_arg;
+ name.str= str_arg;
+ /*
+ We can't trust max_length as in show_routine_code we are using "Pos" as
+ the field name.
+ */
+ name.length= !str_arg[max_length] ? max_length : strlen(str_arg);
fixed= 1;
}
@@ -3009,7 +3279,7 @@ void Item_int::print(String *str, enum_query_type query_type)
Item *Item_bool::neg_transformer(THD *thd)
{
value= !value;
- name= 0;
+ name= null_clex_str;
return this;
}
@@ -3050,7 +3320,8 @@ Item_decimal::Item_decimal(THD *thd, const char *str_arg, uint length,
Item_num(thd)
{
str2my_decimal(E_DEC_FATAL_ERROR, str_arg, length, charset, &decimal_value);
- name= (char*) str_arg;
+ name.str= str_arg;
+ name.length= safe_strlen(str_arg);
decimals= (uint8) decimal_value.frac;
fixed= 1;
max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg +
@@ -3090,7 +3361,8 @@ Item_decimal::Item_decimal(THD *thd, const char *str, const my_decimal *val_arg,
Item_num(thd)
{
my_decimal2decimal(val_arg, &decimal_value);
- name= (char*) str;
+ name.str= str;
+ name.length= safe_strlen(str);
decimals= (uint8) decimal_par;
max_length= length;
fixed= 1;
@@ -3182,7 +3454,7 @@ void Item_decimal::set_decimal_value(my_decimal *value_par)
Item *Item_decimal::clone_item(THD *thd)
{
- return new (thd->mem_root) Item_decimal(thd, name, &decimal_value, decimals,
+ return new (thd->mem_root) Item_decimal(thd, name.str, &decimal_value, decimals,
max_length);
}
@@ -3207,7 +3479,7 @@ my_decimal *Item_float::val_decimal(my_decimal *decimal_value)
Item *Item_float::clone_item(THD *thd)
{
- return new (thd->mem_root) Item_float(thd, name, value, decimals,
+ return new (thd->mem_root) Item_float(thd, name.str, value, decimals,
max_length);
}
@@ -3318,7 +3590,7 @@ Item *Item_null::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
Item *Item_null::clone_item(THD *thd)
{
- return new (thd->mem_root) Item_null(thd, name);
+ return new (thd->mem_root) Item_null(thd, name.str);
}
/*********************** Item_param related ******************************/
@@ -3337,10 +3609,20 @@ default_set_param_func(Item_param *param,
}
-Item_param::Item_param(THD *thd, uint pos_in_query_arg):
+Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg,
+ uint pos_in_query_arg, uint len_in_query_arg):
Item_basic_value(thd),
- Rewritable_query_parameter(pos_in_query_arg, 1),
- Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR),
+ Rewritable_query_parameter(pos_in_query_arg, len_in_query_arg),
+ /*
+ Set handler to type_handler_null. Its data type test methods such as:
+ - is_scalar_type()
+ - can_return_int()
+ - can_return_real(),
+ - is_general_purpose_string_type()
+ all return "true". This is needed to avoid any "illegal parameter type"
+ errors in Item::check_type_xxx() at PS prepare time.
+ */
+ Type_handler_hybrid_field_type(&type_handler_null),
state(NO_VALUE),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
@@ -3356,8 +3638,8 @@ Item_param::Item_param(THD *thd, uint pos_in_query_arg):
*/
m_is_settable_routine_parameter(true)
{
- name= (char*) "?";
- /*
+ name= *name_arg;
+ /*
Since we can't say whenever this item can be NULL or cannot be NULL
before mysql_stmt_execute(), so we assuming that it can be NULL until
value is set.
@@ -3616,47 +3898,10 @@ bool Item_param::set_from_item(THD *thd, Item *item)
}
}
struct st_value tmp;
- if (!item->store(&tmp, 0))
+ if (!item->save_in_value(&tmp))
{
- unsigned_flag= item->unsigned_flag;
- switch (item->cmp_type()) {
- case REAL_RESULT:
- set_double(tmp.value.m_double);
- set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
- break;
- case INT_RESULT:
- set_int(tmp.value.m_longlong, MY_INT64_NUM_DECIMAL_DIGITS);
- set_handler_by_field_type(MYSQL_TYPE_LONGLONG);
- break;
- case STRING_RESULT:
- {
- value.cs_info.set(thd, item->collation.collation);
- /*
- Exact value of max_length is not known unless data is converted to
- charset of connection, so we have to set it later.
- */
- set_handler_by_field_type(MYSQL_TYPE_VARCHAR);
-
- if (set_str(tmp.m_string.ptr(), tmp.m_string.length()))
- DBUG_RETURN(1);
- break;
- }
- case DECIMAL_RESULT:
- {
- set_decimal(&tmp.m_decimal, unsigned_flag);
- set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
- break;
- }
- case TIME_RESULT:
- {
- set_time(&tmp.value.m_time, item->max_length, item->decimals);
- set_handler(item->type_handler());
- break;
- }
- case ROW_RESULT:
- DBUG_ASSERT(0);
- set_null();
- }
+ if (item->type_handler()->Item_param_set_from_value(thd, this, item, &tmp))
+ DBUG_RETURN(true);
}
else
set_null();
@@ -4048,19 +4293,19 @@ Item_param::clone_item(THD *thd)
invalid_default_param();
// fall through
case NULL_VALUE:
- return new (mem_root) Item_null(thd, name);
+ return new (mem_root) Item_null(thd, name.str);
case INT_VALUE:
return (unsigned_flag ?
- new (mem_root) Item_uint(thd, name, value.integer, max_length) :
- new (mem_root) Item_int(thd, name, value.integer, max_length));
+ new (mem_root) Item_uint(thd, name.str, value.integer, max_length) :
+ new (mem_root) Item_int(thd, name.str, value.integer, max_length));
case REAL_VALUE:
- return new (mem_root) Item_float(thd, name, value.real, decimals,
+ return new (mem_root) Item_float(thd, name.str, value.real, decimals,
max_length);
case DECIMAL_VALUE:
return 0; // Should create Item_decimal. See MDEV-11361.
case STRING_VALUE:
case LONG_DATA_VALUE:
- return new (mem_root) Item_string(thd, name, str_value.c_ptr_quick(),
+ return new (mem_root) Item_string(thd, name.str, str_value.c_ptr_quick(),
str_value.length(), str_value.charset(),
collation.derivation,
collation.repertoire);
@@ -4336,7 +4581,6 @@ void Item_param::make_field(THD *thd, Send_field *field)
field->org_col_name= m_out_param_info->org_col_name;
field->length= m_out_param_info->length;
- field->charsetnr= m_out_param_info->charsetnr;
field->flags= m_out_param_info->flags;
field->decimals= m_out_param_info->decimals;
field->type= m_out_param_info->type;
@@ -4694,7 +4938,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
ER_THD(thd,ER_WARN_FIELD_RESOLVED),
db_name, (db_name[0] ? "." : ""),
table_name, (table_name [0] ? "." : ""),
- resolved_item->field_name,
+ resolved_item->field_name.str,
current->select_number, last->select_number);
}
DBUG_RETURN(FALSE);
@@ -4784,7 +5028,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
{
const char *db_name;
const char *table_name;
- const char *field_name;
+ LEX_CSTRING *field_name;
ORDER *found_group= NULL;
int found_match_degree= 0;
char name_buff[SAFE_NAME_LEN+1];
@@ -4794,7 +5038,7 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
{
db_name= ((Item_ident*) find_item)->db_name;
table_name= ((Item_ident*) find_item)->table_name;
- field_name= ((Item_ident*) find_item)->field_name;
+ field_name= &((Item_ident*) find_item)->field_name;
}
else
return NULL;
@@ -4807,17 +5051,17 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
db_name= name_buff;
}
- DBUG_ASSERT(field_name != 0);
+ DBUG_ASSERT(field_name->str != 0);
for (ORDER *cur_group= group_list ; cur_group ; cur_group= cur_group->next)
{
int cur_match_degree= 0;
/* SELECT list element with explicit alias */
- if ((*(cur_group->item))->name &&
+ if ((*(cur_group->item))->name.str &&
!(*(cur_group->item))->is_autogenerated_name &&
!my_strcasecmp(system_charset_info,
- (*(cur_group->item))->name, field_name))
+ (*(cur_group->item))->name.str, field_name->str))
{
++cur_match_degree;
}
@@ -4828,12 +5072,12 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
Item_ident *cur_field= (Item_ident*) *cur_group->item;
const char *l_db_name= cur_field->db_name;
const char *l_table_name= cur_field->table_name;
- const char *l_field_name= cur_field->field_name;
+ LEX_CSTRING *l_field_name= &cur_field->field_name;
- DBUG_ASSERT(l_field_name != 0);
+ DBUG_ASSERT(l_field_name->str != 0);
if (!my_strcasecmp(system_charset_info,
- l_field_name, field_name))
+ l_field_name->str, field_name->str))
++cur_match_degree;
else
continue;
@@ -4969,7 +5213,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
the strict mode is enabled.
*/
my_error(ER_NON_GROUPING_FIELD_USED, MYF(0),
- ref->name, "HAVING");
+ ref->name.str, "HAVING");
return NULL;
}
if (select_ref != not_found_item || group_by_ref)
@@ -4980,7 +5224,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
if (!select->ref_pointer_array[counter])
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0),
- ref->name, "forward reference in item list");
+ ref->name.str, "forward reference in item list");
return NULL;
}
DBUG_ASSERT((*select_ref)->fixed);
@@ -5313,15 +5557,15 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
*ref= NULL; // Don't call set_properties()
rf= (place == IN_HAVING ?
new (thd->mem_root)
- Item_ref(thd, context, ref, (char*) table_name,
- (char*) field_name, alias_name_used) :
+ Item_ref(thd, context, ref, table_name,
+ &field_name, alias_name_used) :
(!select->group_list.elements ?
new (thd->mem_root)
- Item_direct_ref(thd, context, ref, (char*) table_name,
- (char*) field_name, alias_name_used) :
+ Item_direct_ref(thd, context, ref, table_name,
+ &field_name, alias_name_used) :
new (thd->mem_root)
- Item_outer_ref(thd, context, ref, (char*) table_name,
- (char*) field_name, alias_name_used)));
+ Item_outer_ref(thd, context, ref, table_name,
+ &field_name, alias_name_used)));
*ref= save;
if (!rf)
return -1;
@@ -5365,9 +5609,10 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
if (last_checked_context->select_lex->having_fix_field)
{
Item_ref *rf;
- rf= new (thd->mem_root) Item_ref(thd, context, (*from_field)->table->s->db.str,
- (*from_field)->table->alias.c_ptr(),
- (char*) field_name);
+ rf= new (thd->mem_root) Item_ref(thd, context,
+ (*from_field)->table->s->db.str,
+ (*from_field)->table->alias.c_ptr(),
+ &field_name);
if (!rf)
return -1;
thd->change_item_tree(reference, rf);
@@ -5485,7 +5730,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if (new_field == NULL)
{
/* The column to which we link isn't valid. */
- my_error(ER_BAD_FIELD_ERROR, MYF(0), (*res)->name,
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), (*res)->name.str,
thd->where);
return(1);
}
@@ -5506,8 +5751,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
Item_field created by the parser with the new Item_ref.
*/
Item_ref *rf= new (thd->mem_root)
- Item_ref(thd, context, db_name, table_name,
- field_name);
+ Item_ref(thd, context, db_name, table_name, &field_name);
if (!rf)
return 1;
bool err= rf->fix_fields(thd, (Item **) &rf) || rf->check_cols(1);
@@ -5605,16 +5849,16 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (any_privileges)
{
- char *db, *tab;
+ const char *db, *tab;
db= field->table->s->db.str;
tab= field->table->s->table_name.str;
if (!(have_privileges= (get_column_grant(thd, &field->table->grant,
- db, tab, field_name) &
+ db, tab, field_name.str) &
VIEW_ANY_ACL)))
{
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
"ANY", thd->security_ctx->priv_user,
- thd->security_ctx->host_or_ip, field_name, tab);
+ thd->security_ctx->host_or_ip, field_name.str, tab);
goto error;
}
}
@@ -5676,6 +5920,7 @@ error:
return TRUE;
}
+
/*
@brief
Mark virtual columns as used in a partitioning expression
@@ -5866,7 +6111,8 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg)
comparison context, and it's safe to replace it to the constant from
item_equal.
*/
- DBUG_ASSERT(cmp_type() == item_equal->compare_type());
+ DBUG_ASSERT(type_handler()->type_handler_for_comparison()->cmp_type() ==
+ item_equal->compare_type_handler()->cmp_type());
return const_item2;
}
Item_field *subst=
@@ -5883,13 +6129,11 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg)
void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type_arg)
{
- char *empty_name= (char*) "";
- tmp_field->db_name= empty_name;
- tmp_field->org_table_name= empty_name;
- tmp_field->org_col_name= empty_name;
- tmp_field->table_name= empty_name;
- tmp_field->col_name= name;
- tmp_field->charsetnr= collation.collation->number;
+ tmp_field->db_name= "";
+ tmp_field->org_table_name= "";
+ tmp_field->org_col_name= empty_clex_str;
+ tmp_field->table_name= "";
+ tmp_field->col_name= name;
tmp_field->flags= (maybe_null ? 0 : NOT_NULL_FLAG) |
(my_binary_compare(charset_for_protocol()) ?
BINARY_FLAG : 0);
@@ -5908,7 +6152,7 @@ void Item::make_field(THD *thd, Send_field *tmp_field)
void Item_empty_string::make_field(THD *thd, Send_field *tmp_field)
{
- init_make_field(tmp_field, string_field_type());
+ init_make_field(tmp_field, string_type_handler()->field_type());
}
@@ -6042,180 +6286,16 @@ bool Item::eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs)
}
-/**
- Create a field to hold a string value from an item.
-
- If too_big_for_varchar() create a blob @n
- If max_length > 0 create a varchar @n
- If max_length == 0 create a CHAR(0)
-
- @param table Table for which the field is created
-*/
-
-Field *Item::make_string_field(TABLE *table)
-{
- Field *field;
- MEM_ROOT *mem_root= table->in_use->mem_root;
-
- DBUG_ASSERT(collation.collation);
- /*
- Note: the following check is repeated in
- subquery_types_allow_materialization():
- */
- if (too_big_for_varchar())
- field= new (mem_root)
- Field_blob(max_length, maybe_null, name,
- collation.collation, TRUE);
- /* Item_type_holder holds the exact type, do not change it */
- else if (max_length > 0 &&
- (type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING))
- field= new (mem_root)
- Field_varstring(max_length, maybe_null, name, table->s,
- collation.collation);
- else
- field= new (mem_root)
- Field_string(max_length, maybe_null, name, collation.collation);
- if (field)
- field->init(table);
- return field;
-}
-
-
-/**
- Create a field based on field_type of argument.
-
- For now, this is only used to create a field for
- IFNULL(x,something) and time functions
-
- @retval
- NULL error
- @retval
- \# Created field
-*/
-
-Field *Item::tmp_table_field_from_field_type(TABLE *table,
- bool fixed_length,
- bool set_blob_packlength)
-{
- /*
- The field functions defines a field to be not null if null_ptr is not 0
- */
- uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
- Field *field;
- MEM_ROOT *mem_root= table->in_use->mem_root;
-
- switch (field_type()) {
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_NEWDECIMAL:
- field= Field_new_decimal::create_from_item(mem_root, this);
- break;
- case MYSQL_TYPE_TINY:
- field= new (mem_root)
- Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, 0, unsigned_flag);
- break;
- case MYSQL_TYPE_SHORT:
- field= new (mem_root)
- Field_short((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, 0, unsigned_flag);
- break;
- case MYSQL_TYPE_LONG:
- field= new (mem_root)
- Field_long((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, 0, unsigned_flag);
- break;
-#ifdef HAVE_LONG_LONG
- case MYSQL_TYPE_LONGLONG:
- field= new (mem_root)
- Field_longlong((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, 0, unsigned_flag);
- break;
-#endif
- case MYSQL_TYPE_FLOAT:
- field= new (mem_root)
- Field_float((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, decimals, 0, unsigned_flag);
- break;
- case MYSQL_TYPE_DOUBLE:
- field= new (mem_root)
- Field_double((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, decimals, 0, unsigned_flag);
- break;
- case MYSQL_TYPE_INT24:
- field= new (mem_root)
- Field_medium((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
- name, 0, unsigned_flag);
- break;
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_DATE:
- field= new (mem_root)
- Field_newdate(0, null_ptr, 0, Field::NONE, name);
- break;
- case MYSQL_TYPE_TIME:
- field= new_Field_time(mem_root, 0, null_ptr, 0, Field::NONE, name,
- decimals);
- break;
- case MYSQL_TYPE_TIMESTAMP:
- field= new_Field_timestamp(mem_root, 0, null_ptr, 0,
- Field::NONE, name, 0, decimals);
- break;
- case MYSQL_TYPE_DATETIME:
- field= new_Field_datetime(mem_root, 0, null_ptr, 0, Field::NONE, name,
- decimals);
- break;
- case MYSQL_TYPE_YEAR:
- field= new (mem_root)
- Field_year((uchar*) 0, max_length, null_ptr, 0, Field::NONE, name);
- break;
- case MYSQL_TYPE_BIT:
- field= new (mem_root)
- Field_bit_as_char(NULL, max_length, null_ptr, 0, Field::NONE, name);
- break;
- default:
- /* This case should never be chosen */
- DBUG_ASSERT(0);
- /* If something goes awfully wrong, it's better to get a string than die */
- case MYSQL_TYPE_NULL:
- case MYSQL_TYPE_STRING:
- if (fixed_length && !too_big_for_varchar())
- {
- field= new (mem_root)
- Field_string(max_length, maybe_null, name, collation.collation);
- break;
- }
- /* Fall through */
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_VARCHAR:
- return make_string_field(table);
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- field= new (mem_root)
- Field_blob(max_length, maybe_null, name,
- collation.collation, set_blob_packlength);
- break; // Blob handled outside of case
-#ifdef HAVE_SPATIAL
- case MYSQL_TYPE_GEOMETRY:
- field= new (mem_root)
- Field_geom(max_length, maybe_null, name, table->s, get_geometry_type());
-#endif /* HAVE_SPATIAL */
- }
- if (field)
- field->init(table);
- return field;
-}
-
-
/* ARGSUSED */
void Item_field::make_field(THD *thd, Send_field *tmp_field)
{
field->make_field(tmp_field);
DBUG_ASSERT(tmp_field->table_name != 0);
- if (name)
- tmp_field->col_name=name; // Use user supplied name
+ if (name.str)
+ {
+ DBUG_ASSERT(name.length == strlen(name.str));
+ tmp_field->col_name= name; // Use user supplied name
+ }
if (table_name)
tmp_field->table_name= table_name;
if (db_name)
@@ -6363,54 +6443,62 @@ int Item_null::save_safe_in_field(Field *field)
Note: all Item_XXX::val_str(str) methods must NOT assume that
str != str_value. For example, see fix for bug #44743.
*/
+int Item::save_str_in_field(Field *field, bool no_conversions)
+{
+ String *result;
+ CHARSET_INFO *cs= collation.collation;
+ char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
+ str_value.set_quick(buff, sizeof(buff), cs);
+ result=val_str(&str_value);
+ if (null_value)
+ {
+ str_value.set_quick(0, 0, cs);
+ return set_field_to_null_with_conversions(field, no_conversions);
+ }
-int Item::save_in_field(Field *field, bool no_conversions)
+ /* NOTE: If null_value == FALSE, "result" must be not NULL. */
+
+ field->set_notnull();
+ int error= field->store(result->ptr(),result->length(),cs);
+ str_value.set_quick(0, 0, cs);
+ return error;
+}
+
+
+int Item::save_real_in_field(Field *field, bool no_conversions)
{
- int error;
- if (result_type() == STRING_RESULT)
- {
- String *result;
- CHARSET_INFO *cs= collation.collation;
- char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
- str_value.set_quick(buff, sizeof(buff), cs);
- result=val_str(&str_value);
- if (null_value)
- {
- str_value.set_quick(0, 0, cs);
- return set_field_to_null_with_conversions(field, no_conversions);
- }
+ double nr= val_real();
+ if (null_value)
+ return set_field_to_null_with_conversions(field, no_conversions);
+ field->set_notnull();
+ return field->store(nr);
+}
- /* NOTE: If null_value == FALSE, "result" must be not NULL. */
- field->set_notnull();
- error=field->store(result->ptr(),result->length(),cs);
- str_value.set_quick(0, 0, cs);
- }
- else if (result_type() == REAL_RESULT)
- {
- double nr= val_real();
- if (null_value)
- return set_field_to_null_with_conversions(field, no_conversions);
- field->set_notnull();
- error=field->store(nr);
- }
- else if (result_type() == DECIMAL_RESULT)
- {
- my_decimal decimal_value;
- my_decimal *value= val_decimal(&decimal_value);
- if (null_value)
- return set_field_to_null_with_conversions(field, no_conversions);
- field->set_notnull();
- error=field->store_decimal(value);
- }
- else
- {
- longlong nr=val_int();
- if (null_value)
- return set_field_to_null_with_conversions(field, no_conversions);
- field->set_notnull();
- error=field->store(nr, unsigned_flag);
- }
+int Item::save_decimal_in_field(Field *field, bool no_conversions)
+{
+ my_decimal decimal_value;
+ my_decimal *value= val_decimal(&decimal_value);
+ if (null_value)
+ return set_field_to_null_with_conversions(field, no_conversions);
+ field->set_notnull();
+ return field->store_decimal(value);
+}
+
+
+int Item::save_int_in_field(Field *field, bool no_conversions)
+{
+ longlong nr= val_int();
+ if (null_value)
+ return set_field_to_null_with_conversions(field, no_conversions);
+ field->set_notnull();
+ return field->store(nr, unsigned_flag);
+}
+
+
+int Item::save_in_field(Field *field, bool no_conversions)
+{
+ int error= type_handler()->Item_save_in_field(this, field, no_conversions);
return error ? error : (field->table->in_use->is_error() ? 1 : 0);
}
@@ -6432,7 +6520,7 @@ int Item_string::save_in_field(Field *field, bool no_conversions)
Item *Item_string::clone_item(THD *thd)
{
return new (thd->mem_root)
- Item_string(thd, name, str_value.ptr(),
+ Item_string(thd, name.str, str_value.ptr(),
str_value.length(), collation.collation);
}
@@ -6455,7 +6543,7 @@ int Item_int::save_in_field(Field *field, bool no_conversions)
Item *Item_int::clone_item(THD *thd)
{
- return new (thd->mem_root) Item_int(thd, name, value, max_length);
+ return new (thd->mem_root) Item_int(thd, name.str, value, max_length);
}
@@ -6491,9 +6579,9 @@ Item *Item_int_with_ref::clone_item(THD *thd)
*/
return (ref->unsigned_flag ?
new (thd->mem_root)
- Item_uint(thd, ref->name, ref->val_int(), ref->max_length) :
+ Item_uint(thd, ref->name.str, ref->val_int(), ref->max_length) :
new (thd->mem_root)
- Item_int(thd, ref->name, ref->val_int(), ref->max_length));
+ Item_int(thd, ref->name.str, ref->val_int(), ref->max_length));
}
@@ -6521,7 +6609,7 @@ Item *Item_int::neg(THD *thd)
else if (value < 0 && max_length)
max_length--;
value= -value;
- name= 0;
+ name= null_clex_str;
return this;
}
@@ -6529,7 +6617,7 @@ Item *Item_decimal::neg(THD *thd)
{
my_decimal_neg(&decimal_value);
unsigned_flag= 0;
- name= 0;
+ name= null_clex_str;
max_length= my_decimal_precision_to_length_no_truncation(
decimal_value.intg + decimals, decimals, unsigned_flag);
return this;
@@ -6542,7 +6630,8 @@ Item *Item_float::neg(THD *thd)
else if (value < 0 && max_length)
max_length--;
value= -value;
- name= presentation= 0 ;
+ presentation= 0;
+ name= null_clex_str;
return this;
}
@@ -6561,7 +6650,7 @@ Item *Item_uint::neg(THD *thd)
Item *Item_uint::clone_item(THD *thd)
{
- return new (thd->mem_root) Item_uint(thd, name, value, max_length);
+ return new (thd->mem_root) Item_uint(thd, name.str, value, max_length);
}
static uint nr_of_decimals(const char *str, const char *end)
@@ -6631,7 +6720,8 @@ Item_float::Item_float(THD *thd, const char *str_arg, uint length):
my_snprintf(tmp, sizeof(tmp), "%.*s", length, str_arg);
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp);
}
- presentation= name=(char*) str_arg;
+ presentation= name.str= str_arg;
+ name.length= strlen(str_arg);
decimals=(uint8) nr_of_decimals(str_arg, str_arg+length);
max_length=length;
fixed= 1;
@@ -6705,6 +6795,22 @@ void Item_hex_hybrid::print(String *str, enum_query_type query_type)
}
+uint Item_hex_hybrid::decimal_precision() const
+{
+ switch (max_length) {// HEX DEC
+ case 0: // ---- ---
+ case 1: return 3; // 0xFF 255
+ case 2: return 5; // 0xFFFF 65535
+ case 3: return 8; // 0xFFFFFF 16777215
+ case 4: return 10; // 0xFFFFFFFF 4294967295
+ case 5: return 13; // 0xFFFFFFFFFF 1099511627775
+ case 6: return 15; // 0xFFFFFFFFFFFF 281474976710655
+ case 7: return 17; // 0xFFFFFFFFFFFFFF 72057594037927935
+ }
+ return 20; // 0xFFFFFFFFFFFFFFFF 18446744073709551615
+}
+
+
void Item_hex_string::print(String *str, enum_query_type query_type)
{
str->append("X'");
@@ -6852,127 +6958,11 @@ bool Item_time_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
Pack data in buffer for sending.
*/
-bool Item_null::send(Protocol *protocol, String *packet)
+bool Item_null::send(Protocol *protocol, st_value *buffer)
{
return protocol->store_null();
}
-/**
- This is only called from items that is not of type item_field.
-*/
-
-bool Item::send(Protocol *protocol, String *buffer)
-{
- bool UNINIT_VAR(result); // Will be set if null_value == 0
- enum_field_types f_type;
-
- switch ((f_type=field_type())) {
- default:
- case MYSQL_TYPE_NULL:
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_GEOMETRY:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_BIT:
- case MYSQL_TYPE_NEWDECIMAL:
- {
- String *res;
- if ((res=val_str(buffer)))
- {
- DBUG_ASSERT(!null_value);
- result= protocol->store(res->ptr(),res->length(),res->charset());
- }
- else
- {
- DBUG_ASSERT(null_value);
- }
- break;
- }
- case MYSQL_TYPE_TINY:
- {
- longlong nr;
- nr= val_int();
- if (!null_value)
- result= protocol->store_tiny(nr);
- break;
- }
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_YEAR:
- {
- longlong nr;
- nr= val_int();
- if (!null_value)
- result= protocol->store_short(nr);
- break;
- }
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_LONG:
- {
- longlong nr;
- nr= val_int();
- if (!null_value)
- result= protocol->store_long(nr);
- break;
- }
- case MYSQL_TYPE_LONGLONG:
- {
- longlong nr;
- nr= val_int();
- if (!null_value)
- result= protocol->store_longlong(nr, unsigned_flag);
- break;
- }
- case MYSQL_TYPE_FLOAT:
- {
- float nr;
- nr= (float) val_real();
- if (!null_value)
- result= protocol->store(nr, decimals, buffer);
- break;
- }
- case MYSQL_TYPE_DOUBLE:
- {
- double nr= val_real();
- if (!null_value)
- result= protocol->store(nr, decimals, buffer);
- break;
- }
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_TIMESTAMP:
- {
- MYSQL_TIME tm;
- get_date(&tm, sql_mode_for_dates(current_thd));
- if (!null_value)
- {
- if (f_type == MYSQL_TYPE_DATE)
- return protocol->store_date(&tm);
- else
- result= protocol->store(&tm, decimals);
- }
- break;
- }
- case MYSQL_TYPE_TIME:
- {
- MYSQL_TIME tm;
- get_time(&tm);
- if (!null_value)
- result= protocol->store_time(&tm, decimals);
- break;
- }
- }
- if (null_value)
- result= protocol->store_null();
- return result;
-}
-
/**
Check if an item is a constant one and can be cached.
@@ -7026,7 +7016,7 @@ Item* Item::cache_const_expr_transformer(THD *thd, uchar *arg)
if (*(bool*)arg)
{
*((bool*)arg)= FALSE;
- Item_cache *cache= Item_cache::get_cache(thd, this);
+ Item_cache *cache= get_cache(thd);
if (!cache)
return NULL;
cache->setup(thd, this);
@@ -7044,7 +7034,7 @@ bool Item::find_item_processor(void *arg)
return (this == ((Item *) arg));
}
-bool Item_field::send(Protocol *protocol, String *buffer)
+bool Item_field::send(Protocol *protocol, st_value *buffer)
{
return protocol->store(result_field);
}
@@ -7117,7 +7107,7 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
all_fields->push_front((Item*)this, thd->mem_root);
ref= new (thd->mem_root)
Item_ref(thd, &select->context, &ref_pointer_array[el],
- table_name, field_name);
+ table_name, &field_name);
return ref;
}
return this;
@@ -7144,7 +7134,7 @@ Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
if (equal_item->used_tables() == map)
{
field_item= (Item_field *)(equal_item->real_item());
- break;
+ break;
}
}
}
@@ -7152,7 +7142,7 @@ Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
{
Item_ref *ref= new (thd->mem_root) Item_ref(thd, &sel->context,
NullS, NullS,
- field_item->field_name);
+ &field_item->field_name);
return ref;
}
DBUG_ASSERT(0);
@@ -7311,6 +7301,26 @@ void Item_field::print(String *str, enum_query_type query_type)
}
+bool Item_field_row::element_index_by_name(uint *idx,
+ const LEX_CSTRING &name) const
+{
+ Field *field;
+ for (uint i= 0; (field= get_row_field(i)); i++)
+ {
+ // Use the same comparison style with sp_context::find_variable()
+ if (!my_strnncoll(system_charset_info,
+ (const uchar *) field->field_name.str,
+ field->field_name.length,
+ (const uchar *) name.str, name.length))
+ {
+ *idx= i;
+ return false;
+ }
+ }
+ return true;
+}
+
+
void Item_temptable_field::print(String *str, enum_query_type query_type)
{
/*
@@ -7323,7 +7333,7 @@ void Item_temptable_field::print(String *str, enum_query_type query_type)
Item_ref::Item_ref(THD *thd, Name_resolution_context *context_arg,
Item **item, const char *table_name_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg):
Item_ident(thd, context_arg, NullS, table_name_arg, field_name_arg),
ref(item), reference_trough_name(0)
@@ -7368,7 +7378,8 @@ public:
};
Item_ref::Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item,
- const char *field_name_arg, bool alias_name_used_arg):
+ const LEX_CSTRING *field_name_arg,
+ bool alias_name_used_arg):
Item_ident(thd, view_arg, field_name_arg),
ref(item), reference_trough_name(0)
{
@@ -7650,13 +7661,13 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
*/
if (!((*ref)->type() == REF_ITEM &&
((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
- (((*ref)->with_sum_func && name &&
+ (((*ref)->with_sum_func && name.str &&
!(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
current_sel->having_fix_field)) ||
!(*ref)->fixed))
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0),
- name, ((*ref)->with_sum_func?
+ name.str, ((*ref)->with_sum_func?
"reference to group function":
"forward reference in item list"));
goto error;
@@ -7798,11 +7809,11 @@ void Item_ref::print(String *str, enum_query_type query_type)
if (ref)
{
if ((*ref)->type() != Item::CACHE_ITEM && ref_type() != VIEW_REF &&
- !table_name && name && alias_name_used)
+ !table_name && name.str && alias_name_used)
{
THD *thd= current_thd;
- append_identifier(thd, str, (*ref)->real_item()->name,
- strlen((*ref)->real_item()->name));
+ append_identifier(thd, str, (*ref)->real_item()->name.str,
+ (*ref)->real_item()->name.length);
}
else
(*ref)->print(str, query_type);
@@ -7812,11 +7823,11 @@ void Item_ref::print(String *str, enum_query_type query_type)
}
-bool Item_ref::send(Protocol *prot, String *tmp)
+bool Item_ref::send(Protocol *prot, st_value *buffer)
{
if (result_field)
return prot->store(result_field);
- return (*ref)->send(prot, tmp);
+ return (*ref)->send(prot, buffer);
}
@@ -7999,13 +8010,13 @@ void Item_ref::make_field(THD *thd, Send_field *field)
{
(*ref)->make_field(thd, field);
/* Non-zero in case of a view */
- if (name)
+ if (name.str)
field->col_name= name;
if (table_name)
field->table_name= table_name;
if (db_name)
field->db_name= db_name;
- if (orig_field_name)
+ if (orig_field_name.str)
field->org_col_name= orig_field_name;
if (orig_table_name)
field->org_table_name= orig_table_name;
@@ -8111,10 +8122,9 @@ Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg):
with_sum_func= orig_item->with_sum_func;
with_field= orig_item->with_field;
name= item_arg->name;
- name_length= item_arg->name_length;
with_subselect= orig_item->with_subselect;
- if ((expr_value= Item_cache::get_cache(thd, orig_item)))
+ if ((expr_value= orig_item->get_cache(thd)))
expr_value->setup(thd, orig_item);
fixed= 1;
@@ -8172,7 +8182,7 @@ bool Item_cache_wrapper::fix_fields(THD *thd __attribute__((unused)),
return FALSE;
}
-bool Item_cache_wrapper::send(Protocol *protocol, String *buffer)
+bool Item_cache_wrapper::send(Protocol *protocol, st_value *buffer)
{
if (result_field)
return protocol->store(result_field);
@@ -8503,7 +8513,7 @@ Item* Item_cache_wrapper::get_tmp_table_item(THD *thd)
}
-bool Item_direct_view_ref::send(Protocol *protocol, String *buffer)
+bool Item_direct_view_ref::send(Protocol *protocol, st_value *buffer)
{
if (check_null_ref())
return protocol->store_null();
@@ -8818,14 +8828,15 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
real_arg= arg->real_item();
if (real_arg->type() != FIELD_ITEM)
{
- my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str);
goto error;
}
field_arg= (Item_field *)real_arg;
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
{
- my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0),
+ field_arg->field->field_name.str);
goto error;
}
if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of())))
@@ -8905,7 +8916,7 @@ bool Item_default_value::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
return Item_field::get_date(ltime, fuzzydate);
}
-bool Item_default_value::send(Protocol *protocol, String *buffer)
+bool Item_default_value::send(Protocol *protocol, st_value *buffer)
{
calculate();
return Item_field::send(protocol, buffer);
@@ -9012,7 +9023,7 @@ bool Item_ignore_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
return TRUE;
}
-bool Item_ignore_value::send(Protocol *protocol, String *buffer)
+bool Item_ignore_value::send(Protocol *protocol, st_value *buffer)
{
DBUG_ASSERT(0); // never should be called
return TRUE;
@@ -9066,7 +9077,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items)
{
Field *tmp_field= field_arg->field;
/* charset doesn't matter here, it's to avoid sigsegv only */
- tmp_field= new Field_null(0, 0, Field::NONE, field_arg->field->field_name,
+ tmp_field= new Field_null(0, 0, Field::NONE, &field_arg->field->field_name,
&my_charset_bin);
if (tmp_field)
{
@@ -9123,7 +9134,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table,
Try to find field by its name and if it will be found
set field_idx properly.
*/
- (void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
+ (void)find_field_in_table(thd, table, field_name.str, field_name.length,
0, &field_idx);
thd->mark_used_columns= save_mark_used_columns;
triggers= table->triggers;
@@ -9135,8 +9146,8 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
{
return item->type() == TRIGGER_FIELD_ITEM &&
row_version == ((Item_trigger_field *)item)->row_version &&
- !my_strcasecmp(system_charset_info, field_name,
- ((Item_trigger_field *)item)->field_name);
+ !my_strcasecmp(system_charset_info, field_name.str,
+ ((Item_trigger_field *)item)->field_name.str);
}
@@ -9202,9 +9213,11 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items)
{
table_grants->want_privilege= want_privilege;
- if (check_grant_column(thd, table_grants, triggers->trigger_table->s->db.str,
- triggers->trigger_table->s->table_name.str, field_name,
- strlen(field_name), thd->security_ctx))
+ if (check_grant_column(thd, table_grants,
+ triggers->trigger_table->s->db.str,
+ triggers->trigger_table->s->table_name.str,
+ field_name.str, field_name.length,
+ thd->security_ctx))
return TRUE;
}
#endif // NO_EMBEDDED_ACCESS_CHECKS
@@ -9216,7 +9229,7 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items)
return FALSE;
}
- my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name,
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name.str,
(row_version == NEW_ROW) ? "NEW" : "OLD");
return TRUE;
}
@@ -9226,14 +9239,14 @@ void Item_trigger_field::print(String *str, enum_query_type query_type)
{
str->append((row_version == NEW_ROW) ? "NEW" : "OLD", 3);
str->append('.');
- str->append(field_name);
+ str->append(&field_name);
}
bool Item_trigger_field::check_vcol_func_processor(void *arg)
{
const char *ver= row_version == NEW_ROW ? "NEW." : "OLD.";
- return mark_unsupported_function(ver, field_name, arg, VCOL_IMPOSSIBLE);
+ return mark_unsupported_function(ver, field_name.str, arg, VCOL_IMPOSSIBLE);
}
@@ -9270,101 +9283,14 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
Item *item= *ref;
if (item->basic_const_item())
return; // Can't be better
-
- Item *new_item= NULL;
- Item_result res_type= item_cmp_type(comp_item, item);
- char *name= item->name; // Alloced on THD::mem_root
- MEM_ROOT *mem_root= thd->mem_root;
-
- switch (res_type) {
- case TIME_RESULT:
+ Type_handler_hybrid_field_type cmp(comp_item->type_handler_for_comparison());
+ if (!cmp.aggregate_for_comparison(item->type_handler_for_comparison()))
{
- bool is_null;
- Item **ref_copy= ref;
- /* the following call creates a constant and puts it in new_item */
- enum_field_types type= item->field_type_for_temporal_comparison(comp_item);
- get_datetime_value(thd, &ref_copy, &new_item, type, &is_null);
- if (is_null)
- new_item= new (mem_root) Item_null(thd, name);
- break;
- }
- case STRING_RESULT:
- {
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff),&my_charset_bin),*result;
- result=item->val_str(&tmp);
- if (item->null_value)
- new_item= new (mem_root) Item_null(thd, name);
- else
- {
- uint length= result->length();
- char *tmp_str= thd->strmake(result->ptr(), length);
- new_item= new (mem_root) Item_string(thd, name, tmp_str, length, result->charset());
- }
- break;
- }
- case INT_RESULT:
- {
- longlong result=item->val_int();
- uint length=item->max_length;
- bool null_value=item->null_value;
- new_item= (null_value ? (Item*) new (mem_root) Item_null(thd, name) :
- (Item*) new (mem_root) Item_int(thd, name, result, length));
- break;
- }
- case ROW_RESULT:
- if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM)
- {
- /*
- Substitute constants only in Item_row's. Don't affect other Items
- with ROW_RESULT (eg Item_singlerow_subselect).
-
- For such Items more optimal is to detect if it is constant and replace
- it with Item_row. This would optimize queries like this:
- SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
- */
- Item_row *item_row= (Item_row*) item;
- Item_row *comp_item_row= (Item_row*) comp_item;
- uint col;
- new_item= 0;
- /*
- If item and comp_item are both Item_row's and have same number of cols
- then process items in Item_row one by one.
- We can't ignore NULL values here as this item may be used with <=>, in
- which case NULL's are significant.
- */
- DBUG_ASSERT(item->result_type() == comp_item->result_type());
- DBUG_ASSERT(item_row->cols() == comp_item_row->cols());
- col= item_row->cols();
- while (col-- > 0)
- resolve_const_item(thd, item_row->addr(col),
- comp_item_row->element_index(col));
- break;
- }
- /* Fallthrough */
- case REAL_RESULT:
- { // It must REAL_RESULT
- double result= item->val_real();
- uint length=item->max_length,decimals=item->decimals;
- bool null_value=item->null_value;
- new_item= (null_value ? (Item*) new (mem_root) Item_null(thd, name) : (Item*)
- new (mem_root) Item_float(thd, name, result, decimals, length));
- break;
- }
- case DECIMAL_RESULT:
- {
- my_decimal decimal_value;
- my_decimal *result= item->val_decimal(&decimal_value);
- uint length= item->max_length, decimals= item->decimals;
- bool null_value= item->null_value;
- new_item= (null_value ?
- (Item*) new (mem_root) Item_null(thd, name) :
- (Item*) new (mem_root) Item_decimal(thd, name, result, length, decimals));
- break;
- }
+ Item *new_item= cmp.type_handler()->
+ make_const_item_for_comparison(thd, item, comp_item);
+ if (new_item)
+ thd->change_item_tree(ref, new_item);
}
- if (new_item)
- thd->change_item_tree(ref, new_item);
}
/**
@@ -9461,41 +9387,6 @@ int stored_field_cmp_to_item(THD *thd, Field *field, Item *item)
return 0;
}
-Item_cache* Item_cache::get_cache(THD *thd, const Item *item)
-{
- return get_cache(thd, item, item->cmp_type());
-}
-
-
-/**
- Get a cache item of given type.
-
- @param item value to be cached
- @param type required type of cache
-
- @return cache item
-*/
-
-Item_cache* Item_cache::get_cache(THD *thd, const Item *item,
- const Item_result type)
-{
- MEM_ROOT *mem_root= thd->mem_root;
- switch (type) {
- case INT_RESULT:
- return new (mem_root) Item_cache_int(thd, item->field_type());
- case REAL_RESULT:
- return new (mem_root) Item_cache_real(thd);
- case DECIMAL_RESULT:
- return new (mem_root) Item_cache_decimal(thd);
- case STRING_RESULT:
- return new (mem_root) Item_cache_str(thd, item);
- case ROW_RESULT:
- return new (mem_root) Item_cache_row(thd);
- case TIME_RESULT:
- return new (mem_root) Item_cache_temporal(thd, item->field_type());
- }
- return 0; // Impossible
-}
void Item_cache::store(Item *item)
{
@@ -9613,13 +9504,11 @@ Item *Item_cache_int::convert_to_basic_const_item(THD *thd)
}
-Item_cache_temporal::Item_cache_temporal(THD *thd,
- enum_field_types field_type_arg):
- Item_cache_int(thd, field_type_arg)
+Item_cache_temporal::Item_cache_temporal(THD *thd, const Type_handler *handler)
+ :Item_cache_int(thd, handler)
{
- if (mysql_type_to_time_type(Item_cache_temporal::field_type()) ==
- MYSQL_TIMESTAMP_ERROR)
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
+ if (mysql_timestamp_type() == MYSQL_TIMESTAMP_ERROR)
+ set_handler(&type_handler_datetime2);
}
@@ -9727,7 +9616,7 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
}
unpack_time(value, ltime);
- ltime->time_type= mysql_type_to_time_type(field_type());
+ ltime->time_type= mysql_timestamp_type();
if (ltime->time_type == MYSQL_TIMESTAMP_TIME)
{
ltime->hour+= (ltime->month*32+ltime->day)*24;
@@ -9762,7 +9651,7 @@ void Item_cache_temporal::store_packed(longlong val_arg, Item *example_arg)
Item *Item_cache_temporal::clone_item(THD *thd)
{
Item_cache_temporal *item= new (thd->mem_root)
- Item_cache_temporal(thd, Item_cache_temporal::field_type());
+ Item_cache_temporal(thd, Item_cache_temporal::type_handler());
item->store_packed(value, example);
return item;
}
@@ -10020,7 +9909,7 @@ bool Item_cache_row::setup(THD *thd, Item *item)
{
Item *el= item->element_index(i);
Item_cache *tmp;
- if (!(tmp= values[i]= Item_cache::get_cache(thd, el)))
+ if (!(tmp= values[i]= el->get_cache(thd)))
return 1;
tmp->setup(thd, el);
}
@@ -10123,388 +10012,6 @@ void Item_cache_row::set_null()
};
-Item_type_holder::Item_type_holder(THD *thd, Item *item)
- :Item(thd, item),
- Type_handler_hybrid_real_field_type(get_real_type(item)),
- enum_set_typelib(0),
- geometry_type(Field::GEOM_GEOMETRY)
-{
- DBUG_ASSERT(item->fixed);
- maybe_null= item->maybe_null;
- collation.set(item->collation);
- get_full_info(item);
- /**
- Field::result_merge_type(real_field_type()) should be equal to
- result_type(), with one exception when "this" is a Item_field for
- a BIT field:
- - Field_bit::result_type() returns INT_RESULT, so does its Item_field.
- - Field::result_merge_type(MYSQL_TYPE_BIT) returns STRING_RESULT.
- Perhaps we need a new method in Type_handler to cover these type
- merging rules for UNION.
- */
- DBUG_ASSERT(real_field_type() == MYSQL_TYPE_BIT ||
- Item_type_holder::result_type() ==
- Field::result_merge_type(Item_type_holder::real_field_type()));
- /* fix variable decimals which always is NOT_FIXED_DEC */
- if (Field::result_merge_type(real_field_type()) == INT_RESULT)
- decimals= 0;
- prev_decimal_int_part= item->decimal_int_part();
-#ifdef HAVE_SPATIAL
- if (item->field_type() == MYSQL_TYPE_GEOMETRY)
- geometry_type= item->get_geometry_type();
-#endif /* HAVE_SPATIAL */
-}
-
-
-/**
- Find real field type of item.
-
- @return
- type of field which should be created to store item value
-*/
-
-enum_field_types Item_type_holder::get_real_type(Item *item)
-{
- if (item->type() == REF_ITEM)
- item= item->real_item();
- switch(item->type())
- {
- case FIELD_ITEM:
- {
- /*
- Item_field::field_type ask Field_type() but sometimes field return
- a different type, like for enum/set, so we need to ask real type.
- */
- Field *field= ((Item_field *) item)->field;
- enum_field_types type= field->real_type();
- if (field->is_created_from_null_item)
- return MYSQL_TYPE_NULL;
- /* work around about varchar type field detection */
- if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
- return MYSQL_TYPE_VAR_STRING;
- return type;
- }
- case SUM_FUNC_ITEM:
- {
- /*
- Argument of aggregate function sometimes should be asked about field
- type
- */
- Item_sum *item_sum= (Item_sum *) item;
- if (item_sum->keep_field_type())
- return get_real_type(item_sum->get_arg(0));
- break;
- }
- case FUNC_ITEM:
- if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
- {
- /*
- There are work around of problem with changing variable type on the
- fly and variable always report "string" as field type to get
- acceptable information for client in send_field, so we make field
- type from expression type.
- */
- switch (item->result_type()) {
- case STRING_RESULT:
- return MYSQL_TYPE_VARCHAR;
- case INT_RESULT:
- return MYSQL_TYPE_LONGLONG;
- case REAL_RESULT:
- return MYSQL_TYPE_DOUBLE;
- case DECIMAL_RESULT:
- return MYSQL_TYPE_NEWDECIMAL;
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- return MYSQL_TYPE_VARCHAR;
- }
- }
- break;
- case TYPE_HOLDER:
- /*
- Item_type_holder and Item_blob should not appear in this context.
- In case they for some reasons do, returning field_type() is wrong anyway.
- They must return Item_type_holder::real_field_type() instead, to make
- the code in sql_type.cc and sql_type.h happy, as it expectes
- Field::real_type()-compatible rather than Field::field_type()-compatible
- valies in some places, and may in the future add some asserts preventing
- use of field_type() instead of real_type() and the other way around.
- */
- DBUG_ASSERT(0);
- default:
- break;
- }
- return item->field_type();
-}
-
-/**
- Find field type which can carry current Item_type_holder type and
- type of given Item.
-
- @param thd thread handler
- @param item given item to join its parameters with this item ones
-
- @retval
- TRUE error - types are incompatible
- @retval
- FALSE OK
-*/
-
-bool Item_type_holder::join_types(THD *thd, Item *item)
-{
- uint max_length_orig= max_length;
- uint decimals_orig= decimals;
- DBUG_ENTER("Item_type_holder::join_types");
- DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s",
- real_field_type(), max_length, decimals,
- (name ? name : "<NULL>")));
- DBUG_PRINT("info:", ("in type %d len %d, dec %d",
- get_real_type(item),
- item->max_length, item->decimals));
- set_handler_by_real_type(Field::field_type_merge(real_field_type(),
- get_real_type(item)));
- {
- uint item_decimals= item->decimals;
- /* fix variable decimals which always is NOT_FIXED_DEC */
- if (Field::result_merge_type(real_field_type()) == INT_RESULT)
- item_decimals= 0;
- decimals= MY_MAX(decimals, item_decimals);
- }
-
- if (Item_type_holder::field_type() == FIELD_TYPE_GEOMETRY)
- geometry_type=
- Field_geom::geometry_type_merge(geometry_type, item->get_geometry_type());
-
- if (Field::result_merge_type(real_field_type()) == DECIMAL_RESULT)
- {
- decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE);
- int item_int_part= item->decimal_int_part();
- int item_prec = MY_MAX(prev_decimal_int_part, item_int_part) + decimals;
- int precision= MY_MIN(item_prec, DECIMAL_MAX_PRECISION);
- unsigned_flag&= item->unsigned_flag;
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- }
-
- switch (Field::result_merge_type(real_field_type()))
- {
- case STRING_RESULT:
- {
- const char *old_cs, *old_derivation;
- uint32 old_max_chars= max_length / collation.collation->mbmaxlen;
- old_cs= collation.collation->name;
- old_derivation= collation.derivation_name();
- if (collation.aggregate(item->collation, MY_COLL_ALLOW_CONV))
- {
- my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
- old_cs, old_derivation,
- item->collation.collation->name,
- item->collation.derivation_name(),
- "UNION");
- DBUG_RETURN(TRUE);
- }
- /*
- To figure out max_length, we have to take into account possible
- expansion of the size of the values because of character set
- conversions.
- */
- if (collation.collation != &my_charset_bin)
- {
- max_length= MY_MAX(old_max_chars * collation.collation->mbmaxlen,
- display_length(item) /
- item->collation.collation->mbmaxlen *
- collation.collation->mbmaxlen);
- }
- else
- set_if_bigger(max_length, display_length(item));
- break;
- }
- case REAL_RESULT:
- {
- if (decimals != NOT_FIXED_DEC)
- {
- /*
- For FLOAT(M,D)/DOUBLE(M,D) do not change precision
- if both fields have the same M and D
- */
- if (item->max_length != max_length_orig ||
- item->decimals != decimals_orig)
- {
- int delta1= max_length_orig - decimals_orig;
- int delta2= item->max_length - item->decimals;
- max_length= MY_MAX(delta1, delta2) + decimals;
- if (Item_type_holder::real_field_type() == MYSQL_TYPE_FLOAT &&
- max_length > FLT_DIG + 2)
- {
- max_length= MAX_FLOAT_STR_LENGTH;
- decimals= NOT_FIXED_DEC;
- }
- else if (Item_type_holder::real_field_type() == MYSQL_TYPE_DOUBLE &&
- max_length > DBL_DIG + 2)
- {
- max_length= MAX_DOUBLE_STR_LENGTH;
- decimals= NOT_FIXED_DEC;
- }
- }
- }
- else
- max_length= (Item_type_holder::field_type() == MYSQL_TYPE_FLOAT) ?
- FLT_DIG+6 : DBL_DIG+7;
- break;
- }
- default:
- max_length= MY_MAX(max_length, display_length(item));
- };
- maybe_null|= item->maybe_null;
- get_full_info(item);
-
- /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
- prev_decimal_int_part= decimal_int_part();
- DBUG_PRINT("info", ("become type: %d len: %u dec: %u",
- (int) real_field_type(), max_length, (uint) decimals));
- DBUG_RETURN(FALSE);
-}
-
-/**
- Calculate lenth for merging result for given Item type.
-
- @param item Item for length detection
-
- @return
- length
-*/
-
-uint32 Item_type_holder::display_length(Item *item)
-{
- if (item->type() == Item::FIELD_ITEM)
- return ((Item_field *)item)->max_disp_length();
-
- switch (item->field_type())
- {
- case MYSQL_TYPE_DECIMAL:
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_BIT:
- case MYSQL_TYPE_NEWDECIMAL:
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_VAR_STRING:
- case MYSQL_TYPE_STRING:
- case MYSQL_TYPE_GEOMETRY:
- return item->max_length;
- case MYSQL_TYPE_TINY:
- return 4;
- case MYSQL_TYPE_SHORT:
- return 6;
- case MYSQL_TYPE_LONG:
- return MY_INT32_NUM_DECIMAL_DIGITS;
- case MYSQL_TYPE_FLOAT:
- return 25;
- case MYSQL_TYPE_DOUBLE:
- return 53;
- case MYSQL_TYPE_NULL:
- return 0;
- case MYSQL_TYPE_LONGLONG:
- return 20;
- case MYSQL_TYPE_INT24:
- return 8;
- default:
- DBUG_ASSERT(0); // we should never go there
- return 0;
- }
-}
-
-
-/**
- Make temporary table field according collected information about type
- of UNION result.
-
- @param table temporary table for which we create fields
-
- @return
- created field
-*/
-
-Field *Item_type_holder::make_field_by_type(TABLE *table)
-{
- /*
- The field functions defines a field to be not null if null_ptr is not 0
- */
- uchar *null_ptr= maybe_null ? (uchar*) "" : 0;
- Field *field;
-
- switch (Item_type_holder::real_field_type()) {
- case MYSQL_TYPE_ENUM:
- DBUG_ASSERT(enum_set_typelib);
- field= new Field_enum((uchar *) 0, max_length, null_ptr, 0,
- Field::NONE, name,
- get_enum_pack_length(enum_set_typelib->count),
- enum_set_typelib, collation.collation);
- if (field)
- field->init(table);
- return field;
- case MYSQL_TYPE_SET:
- DBUG_ASSERT(enum_set_typelib);
- field= new Field_set((uchar *) 0, max_length, null_ptr, 0,
- Field::NONE, name,
- get_set_pack_length(enum_set_typelib->count),
- enum_set_typelib, collation.collation);
- if (field)
- field->init(table);
- return field;
- case MYSQL_TYPE_NULL:
- return make_string_field(table);
- default:
- break;
- }
- return tmp_table_field_from_field_type(table, false, true);
-}
-
-
-/**
- Get full information from Item about enum/set fields to be able to create
- them later.
-
- @param item Item for information collection
-*/
-void Item_type_holder::get_full_info(Item *item)
-{
- if (Item_type_holder::real_field_type() == MYSQL_TYPE_ENUM ||
- Item_type_holder::real_field_type() == MYSQL_TYPE_SET)
- {
- if (item->type() == Item::SUM_FUNC_ITEM &&
- (((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
- ((Item_sum*)item)->sum_func() == Item_sum::MIN_FUNC))
- item = ((Item_sum*)item)->get_arg(0);
- /*
- We can have enum/set type after merging only if we have one enum|set
- field (or MIN|MAX(enum|set field)) and number of NULL fields
- */
- DBUG_ASSERT((enum_set_typelib &&
- get_real_type(item) == MYSQL_TYPE_NULL) ||
- (!enum_set_typelib &&
- item->real_item()->type() == Item::FIELD_ITEM &&
- (get_real_type(item->real_item()) == MYSQL_TYPE_ENUM ||
- get_real_type(item->real_item()) == MYSQL_TYPE_SET) &&
- ((Field_enum*)((Item_field *) item->real_item())->field)->typelib));
- if (!enum_set_typelib)
- {
- enum_set_typelib= ((Field_enum*)((Item_field *) item->real_item())->field)->typelib;
- }
- }
-}
-
-
double Item_type_holder::val_real()
{
DBUG_ASSERT(0); // should never be called
diff --git a/sql/item.h b/sql/item.h
index cee88756bbf..945e388fd60 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -55,6 +55,23 @@ struct st_value
C_MODE_END
+
+template<size_t buffer_size>
+class ValueBuffer: public st_value
+{
+ char buffer[buffer_size];
+ void reset_buffer()
+ {
+ m_string.set(buffer, buffer_size, &my_charset_bin);
+ }
+public:
+ ValueBuffer()
+ {
+ reset_buffer();
+ }
+};
+
+
const char *dbug_print_item(Item *item);
class Protocol;
@@ -96,13 +113,6 @@ enum precedence {
typedef Bounds_checked_array<Item*> Ref_ptr_array;
-static inline uint32
-char_to_byte_length_safe(size_t char_length_arg, uint32 mbmaxlen_arg)
-{
- ulonglong tmp= ((ulonglong) char_length_arg) * mbmaxlen_arg;
- return tmp > UINT_MAX32 ? UINT_MAX32 : static_cast<uint32>(tmp);
-}
-
bool mark_unsupported_function(const char *where, void *store, uint result);
/* convenience helper for mark_unsupported_function() above */
@@ -113,124 +123,12 @@ bool mark_unsupported_function(const char *w1, const char *w2,
#define SPLIT_SUM_SKIP_REGISTERED 1 /* Skip registered funcs */
#define SPLIT_SUM_SELECT 2 /* SELECT item; Split all parts */
-/*
- "Declared Type Collation"
- A combination of collation and its derivation.
-
- Flags for collation aggregation modes:
- MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
- MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
- (i.e. constant).
- MY_COLL_ALLOW_CONV - allow any kind of conversion
- (combination of the above two)
- MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to
- @@character_set_connection
- MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE
- (e.g. when aggregating for comparison)
- MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV
- and MY_COLL_DISALLOW_NONE
-*/
-
-#define MY_COLL_ALLOW_SUPERSET_CONV 1
-#define MY_COLL_ALLOW_COERCIBLE_CONV 2
-#define MY_COLL_DISALLOW_NONE 4
-#define MY_COLL_ALLOW_NUMERIC_CONV 8
-
-#define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV)
-#define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE)
#define NO_EXTRACTION_FL (1 << 6)
#define FULL_EXTRACTION_FL (1 << 7)
#define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL)
-class DTCollation {
-public:
- CHARSET_INFO *collation;
- enum Derivation derivation;
- uint repertoire;
-
- void set_repertoire_from_charset(CHARSET_INFO *cs)
- {
- repertoire= cs->state & MY_CS_PUREASCII ?
- MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
- }
- DTCollation()
- {
- collation= &my_charset_bin;
- derivation= DERIVATION_NONE;
- repertoire= MY_REPERTOIRE_UNICODE30;
- }
- DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg)
- {
- collation= collation_arg;
- derivation= derivation_arg;
- set_repertoire_from_charset(collation_arg);
- }
- DTCollation(CHARSET_INFO *collation_arg,
- Derivation derivation_arg,
- uint repertoire_arg)
- :collation(collation_arg),
- derivation(derivation_arg),
- repertoire(repertoire_arg)
- { }
- void set(const DTCollation &dt)
- {
- collation= dt.collation;
- derivation= dt.derivation;
- repertoire= dt.repertoire;
- }
- void set(CHARSET_INFO *collation_arg, Derivation derivation_arg)
- {
- collation= collation_arg;
- derivation= derivation_arg;
- set_repertoire_from_charset(collation_arg);
- }
- void set(CHARSET_INFO *collation_arg,
- Derivation derivation_arg,
- uint repertoire_arg)
- {
- collation= collation_arg;
- derivation= derivation_arg;
- repertoire= repertoire_arg;
- }
- void set_numeric()
- {
- collation= &my_charset_numeric;
- derivation= DERIVATION_NUMERIC;
- repertoire= MY_REPERTOIRE_NUMERIC;
- }
- void set(CHARSET_INFO *collation_arg)
- {
- collation= collation_arg;
- set_repertoire_from_charset(collation_arg);
- }
- void set(Derivation derivation_arg)
- { derivation= derivation_arg; }
- bool aggregate(const DTCollation &dt, uint flags= 0);
- bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0)
- { set(dt1); return aggregate(dt2, flags); }
- const char *derivation_name() const
- {
- switch(derivation)
- {
- case DERIVATION_NUMERIC: return "NUMERIC";
- case DERIVATION_IGNORABLE: return "IGNORABLE";
- case DERIVATION_COERCIBLE: return "COERCIBLE";
- case DERIVATION_IMPLICIT: return "IMPLICIT";
- case DERIVATION_SYSCONST: return "SYSCONST";
- case DERIVATION_EXPLICIT: return "EXPLICIT";
- case DERIVATION_NONE: return "NONE";
- default: return "UNKNOWN";
- }
- }
- int sortcmp(const String *s, const String *t) const
- {
- return collation->coll->strnncollsp(collation,
- (uchar *) s->ptr(), s->length(),
- (uchar *) t->ptr(), t->length());
- }
-};
-
+extern const char *item_empty_name;
void dummy_error_processor(THD *thd, void *data);
@@ -496,7 +394,7 @@ class Rewritable_query_parameter
/*
Byte length of parameter name in the statement. This is not
- Item::name_length because name_length contains byte length of UTF8-encoded
+ Item::name.length because name.length contains byte length of UTF8-encoded
name, but the query string is in the client charset.
*/
uint len_in_query;
@@ -601,49 +499,8 @@ public:
};
-/**
- A class to store type attributes for the standard data types.
- Does not include attributes for the extended data types
- such as ENUM, SET, GEOMETRY.
-*/
-class Type_std_attributes
-{
-public:
- DTCollation collation;
- uint decimals;
- /*
- The maximum value length in characters multiplied by collation->mbmaxlen.
- Almost always it's the maximum value length in bytes.
- */
- uint32 max_length;
- bool unsigned_flag;
- Type_std_attributes()
- :collation(&my_charset_bin, DERIVATION_COERCIBLE),
- decimals(0), max_length(0), unsigned_flag(false)
- { }
- Type_std_attributes(const Type_std_attributes *other)
- :collation(other->collation),
- decimals(other->decimals),
- max_length(other->max_length),
- unsigned_flag(other->unsigned_flag)
- { }
- void set(const Type_std_attributes *other)
- {
- *this= *other;
- }
- void set(const Field *field)
- {
- decimals= field->decimals();
- max_length= field->field_length;
- collation.set(field->charset());
- unsigned_flag= MY_TEST(field->flags & UNSIGNED_FLAG);
- }
-};
-
-
class Item: public Value_source,
- public Type_std_attributes,
- public Type_handler
+ public Type_all_attributes
{
void operator=(Item &);
/**
@@ -696,14 +553,76 @@ protected:
SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param);
- virtual Field *make_string_field(TABLE *table);
- Field *tmp_table_field_from_field_type(TABLE *table,
- bool fixed_length,
- bool set_blob_packlength);
- Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length);
+ /**
+ Create a field based on the exact data type handler.
+ */
+ Field *create_table_field_from_handler(TABLE *table)
+ {
+ const Type_handler *h= type_handler();
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ /**
+ Create a field based on field_type of argument.
+ This is used to create a field for
+ - IFNULL(x,something)
+ - time functions
+ - prepared statement placeholders
+ - SP variables with data type references: DECLARE a TYPE OF t1.a;
+ @retval NULL error
+ @retval !NULL on success
+ */
+ Field *tmp_table_field_from_field_type(TABLE *table)
+ {
+ const Type_handler *h= type_handler()->type_handler_for_tmp_table(this);
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ Field *create_tmp_field_int(TABLE *table, uint convert_int_length);
void push_note_converted_to_negative_complement(THD *thd);
void push_note_converted_to_positive_complement(THD *thd);
+
+ /* Helper methods, to get an Item value from another Item */
+ double val_real_from_item(Item *item)
+ {
+ DBUG_ASSERT(fixed == 1);
+ double value= item->val_real();
+ null_value= item->null_value;
+ return value;
+ }
+ longlong val_int_from_item(Item *item)
+ {
+ DBUG_ASSERT(fixed == 1);
+ longlong value= item->val_int();
+ null_value= item->null_value;
+ return value;
+ }
+ String *val_str_from_item(Item *item, String *str)
+ {
+ DBUG_ASSERT(fixed == 1);
+ String *res= item->val_str(str);
+ if (res)
+ res->set_charset(collation.collation);
+ if ((null_value= item->null_value))
+ res= NULL;
+ return res;
+ }
+ my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value)
+ {
+ DBUG_ASSERT(fixed == 1);
+ my_decimal *value= item->val_decimal(decimal_value);
+ if ((null_value= item->null_value))
+ value= NULL;
+ return value;
+ }
+ bool get_date_with_conversion_from_item(Item *item,
+ MYSQL_TIME *ltime, uint fuzzydate)
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (null_value= item->get_date_with_conversion(ltime, fuzzydate));
+ }
+
public:
/*
Cache val_str() into the own buffer, e.g. to evaluate constant
@@ -711,9 +630,9 @@ public:
*/
String *val_str() { return val_str(&str_value); }
- char * name; /* Name from select */
+ LEX_CSTRING name; /* Name of item */
/* Original item name (if it was renamed)*/
- char * orig_name;
+ const char *orig_name;
/**
Intrusive list pointer for free list. If not null, points to the next
Item on some Query_arena's free list. For instance, stored procedures
@@ -722,12 +641,6 @@ public:
@see Query_arena::free_list
*/
Item *next;
- /*
- TODO: convert name and name_length fields into LEX_STRING to keep them in
- sync (see bug #11829681/60295 etc). Then also remove some strlen(name)
- calls.
- */
- uint name_length; /* Length of name */
int marker;
bool maybe_null; /* If item may be null */
bool in_rollup; /* If used in GROUP BY list
@@ -759,15 +672,13 @@ public:
virtual ~Item()
{
#ifdef EXTRA_DEBUG
- name=0;
+ name.str= 0;
+ name.length= 0;
#endif
} /*lint -e1509 */
void set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs);
void set_name_no_truncate(THD *thd, const char *str, uint length,
CHARSET_INFO *cs);
- void set_name_for_rollback(THD *thd, const char *str, uint length,
- CHARSET_INFO *cs);
- void rename(char *new_name);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual void cleanup();
virtual void make_field(THD *thd, Send_field *field);
@@ -791,54 +702,9 @@ public:
*/
virtual inline void quick_fix_field() { fixed= 1; }
- bool store(struct st_value *value, ulonglong fuzzydate)
+ bool save_in_value(struct st_value *value)
{
- switch (cmp_type()) {
- case INT_RESULT:
- {
- value->m_type= unsigned_flag ? DYN_COL_UINT : DYN_COL_INT;
- value->value.m_longlong= val_int();
- break;
- }
- case REAL_RESULT:
- {
- value->m_type= DYN_COL_DOUBLE;
- value->value.m_double= val_real();
- break;
- }
- case DECIMAL_RESULT:
- {
- value->m_type= DYN_COL_DECIMAL;
- my_decimal *dec= val_decimal(&value->m_decimal);
- if (dec != &value->m_decimal && !null_value)
- my_decimal2decimal(dec, &value->m_decimal);
- break;
- }
- case STRING_RESULT:
- {
- value->m_type= DYN_COL_STRING;
- String *str= val_str(&value->m_string);
- if (str != &value->m_string && !null_value)
- value->m_string.set(str->ptr(), str->length(), str->charset());
- break;
- }
- case TIME_RESULT:
- {
- value->m_type= DYN_COL_DATETIME;
- get_date(&value->value.m_time, fuzzydate);
- break;
- }
- case ROW_RESULT:
- DBUG_ASSERT(false);
- null_value= true;
- break;
- }
- if (null_value)
- {
- value->m_type= DYN_COL_NULL;
- return true;
- }
- return false;
+ return type_handler()->Item_save_in_value(this, value);
}
/* Function returns 1 on overflow and -1 on fatal errors */
@@ -853,42 +719,80 @@ public:
{ return NULL; }
virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); }
- virtual bool send(Protocol *protocol, String *str);
+ virtual bool send(Protocol *protocol, st_value *buffer)
+ {
+ return type_handler()->Item_send(this, protocol, buffer);
+ }
virtual bool eq(const Item *, bool binary_cmp) const;
- const Type_handler *type_handler() const
+ enum_field_types field_type() const
+ {
+ return type_handler()->field_type();
+ }
+ virtual const Type_handler *type_handler() const= 0;
+ const Type_handler *type_handler_for_comparison() const
{
- return get_handler_by_field_type(field_type());
+ return type_handler()->type_handler_for_comparison();
}
- Field *make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
- const Item *item) const
+ virtual const Type_handler *real_type_handler() const
{
- return type_handler()->make_num_distinct_aggregator_field(mem_root, this);
+ return type_handler();
}
- Field *make_conversion_table_field(TABLE *table,
- uint metadata, const Field *target) const
+ virtual const Type_handler *cast_to_int_type_handler() const
{
- DBUG_ASSERT(0); // Should not be called in Item context
- return NULL;
+ return type_handler();
}
/* result_type() of an item specifies how the value should be returned */
- Item_result result_type() const { return type_handler()->result_type(); }
+ Item_result result_type() const
+ {
+ return type_handler()->result_type();
+ }
/* ... while cmp_type() specifies how it should be compared */
- Item_result cmp_type() const { return type_handler()->cmp_type(); }
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+ Item_result cmp_type() const
+ {
+ return type_handler()->cmp_type();
+ }
+ const Type_handler *string_type_handler() const
+ {
+ return Type_handler::string_type_handler(max_length);
+ }
+ /*
+ Calculate the maximum length of an expression.
+ This method is used in data type aggregation for UNION, e.g.:
+ SELECT 'b' UNION SELECT COALESCE(double_10_3_field) FROM t1;
+
+ The result is usually equal to max_length, except for some numeric types.
+ In case of the INT, FLOAT, DOUBLE data types Item::max_length and
+ Item::decimals are ignored, so the returned value depends only on the
+ data type itself. E.g. for an expression of the DOUBLE(10,3) data type,
+ the result is always 53 (length 10 and precision 3 do not matter).
+
+ max_length is ignored for these numeric data types because the length limit
+ means only "expected maximum length", it is not a hard limit, so it does
+ not impose any data truncation. E.g. a column of the type INT(4) can
+ normally store big values up to 2147483647 without truncation. When we're
+ aggregating such column for UNION it's important to create a long enough
+ result column, not to lose any data.
+
+ For detailed behaviour of various data types see implementations of
+ the corresponding Type_handler_xxx::max_display_length().
+
+ Note, Item_field::max_display_length() overrides this to get
+ max_display_length() from the underlying field.
+ */
+ virtual uint32 max_display_length() const
{
- type_handler()->make_sort_key(to, item, sort_field, param);
+ return type_handler()->max_display_length(this);
}
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const
+ TYPELIB *get_typelib() const { return NULL; }
+ void set_maybe_null(bool maybe_null_arg) { maybe_null= maybe_null_arg; }
+ void set_typelib(TYPELIB *typelib)
{
- type_handler()->sortlength(thd, item, attr);
+ // Non-field Items (e.g. hybrid functions) never have ENUM/SET types yet.
+ DBUG_ASSERT(0);
}
- virtual Item_result cast_to_int_type() const { return cmp_type(); }
- enum_field_types string_field_type() const
+ Item_cache* get_cache(THD *thd) const
{
- return Type_handler::string_type_handler(max_length)->field_type();
+ return type_handler()->Item_get_cache(thd, this);
}
virtual enum Type type() const =0;
/*
@@ -972,20 +876,45 @@ public:
to negative complements.
Values of non-integer data types are adjusted to the SIGNED range.
*/
- virtual longlong val_int_signed_typecast();
+ virtual longlong val_int_signed_typecast()
+ {
+ return cast_to_int_type_handler()->Item_val_int_signed_typecast(this);
+ }
+ longlong val_int_signed_typecast_from_str();
/**
Get a value for CAST(x AS UNSIGNED).
Negative signed integer values are converted
to positive complements.
Values of non-integer data types are adjusted to the UNSIGNED range.
*/
- virtual longlong val_int_unsigned_typecast();
+ virtual longlong val_int_unsigned_typecast()
+ {
+ return cast_to_int_type_handler()->Item_val_int_unsigned_typecast(this);
+ }
+ longlong val_int_unsigned_typecast_from_decimal();
+ longlong val_int_unsigned_typecast_from_int();
+ longlong val_int_unsigned_typecast_from_str();
/*
This is just a shortcut to avoid the cast. You should still use
unsigned_flag to check the sign of the item.
*/
inline ulonglong val_uint() { return (ulonglong) val_int(); }
/*
+ Adjust the result of val_int() to an unsigned number:
+ - NULL value is converted to 0. The caller can check "null_value"
+ to distinguish between 0 and NULL when necessary.
+ - Negative numbers are converted to 0.
+ - Positive numbers bigger than upper_bound are converted to upper_bound.
+ - Other numbers are returned as is.
+ */
+ ulonglong val_uint_from_val_int(ulonglong upper_bound)
+ {
+ longlong nr= val_int();
+ return (null_value || (nr < 0 && !unsigned_flag)) ? 0 :
+ (ulonglong) nr > upper_bound ? upper_bound : (ulonglong) nr;
+ }
+
+ /*
Return string representation of this item object.
SYNOPSIS
@@ -1157,16 +1086,21 @@ public:
// Check NULL value for a TIME, DATE or DATETIME expression
bool is_null_from_temporal();
- int save_time_in_field(Field *field);
- int save_date_in_field(Field *field);
+ int save_time_in_field(Field *field, bool no_conversions);
+ int save_date_in_field(Field *field, bool no_conversions);
+ int save_str_in_field(Field *field, bool no_conversions);
+ int save_real_in_field(Field *field, bool no_conversions);
+ int save_int_in_field(Field *field, bool no_conversions);
+ int save_decimal_in_field(Field *field, bool no_conversions);
+
int save_str_value_in_field(Field *field, String *result);
virtual Field *get_tmp_table_field() { return 0; }
virtual Field *create_field_for_create_select(TABLE *table);
virtual Field *create_field_for_schema(THD *thd, TABLE *table);
- virtual const char *full_name() const { return name ? name : "???"; }
+ virtual const char *full_name() const { return name.str ? name.str : "???"; }
const char *field_name_or_null()
- { return real_item()->type() == Item::FIELD_ITEM ? name : NULL; }
+ { return real_item()->type() == Item::FIELD_ITEM ? name.str : NULL; }
/*
*result* family of methods is analog of *val* family (see above) but
@@ -1217,7 +1151,10 @@ public:
inline uint float_length(uint decimals_par) const
{ return decimals < FLOATING_POINT_DECIMALS ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
/* Returns total number of decimal digits */
- virtual uint decimal_precision() const;
+ virtual uint decimal_precision() const
+ {
+ return type_handler()->Item_decimal_precision(this);
+ }
/* Returns the number of integer part digits only */
inline int decimal_int_part() const
{ return my_decimal_int_part(decimal_precision(), decimals); }
@@ -1228,10 +1165,7 @@ public:
*/
uint decimal_scale() const
{
- return decimals < NOT_FIXED_DEC ? decimals :
- is_temporal_type_with_time(field_type()) ?
- TIME_SECOND_PART_DIGITS :
- MY_MIN(max_length, DECIMAL_MAX_SCALE);
+ return type_handler()->Item_decimal_scale(this);
}
/*
Returns how many digits a divisor adds into a division result.
@@ -1252,15 +1186,25 @@ public:
*/
uint divisor_precision_increment() const
{
- return decimals < NOT_FIXED_DEC ? decimals :
- is_temporal_type_with_time(field_type()) ?
- TIME_SECOND_PART_DIGITS :
- decimals;
+ return type_handler()->Item_divisor_precision_increment(this);
}
/**
TIME or DATETIME precision of the item: 0..6
*/
- uint temporal_precision(enum_field_types type);
+ uint time_precision()
+ {
+ return const_item() ? type_handler()->Item_time_precision(this) :
+ MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+ }
+ uint datetime_precision()
+ {
+ return const_item() ? type_handler()->Item_datetime_precision(this) :
+ MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+ }
+ virtual longlong val_int_min() const
+ {
+ return LONGLONG_MIN;
+ }
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
@@ -1410,28 +1354,6 @@ public:
return f_type == MYSQL_TYPE_TIME ? val_time_packed() :
val_datetime_packed();
}
- enum_field_types field_type_for_temporal_comparison(const Item *other) const
- {
- if (cmp_type() == TIME_RESULT)
- {
- if (other->cmp_type() == TIME_RESULT)
- return Field::field_type_merge(field_type(), other->field_type());
- else
- return field_type();
- }
- else
- {
- if (other->cmp_type() == TIME_RESULT)
- return other->field_type();
- DBUG_ASSERT(0); // Two non-temporal data types, we should not get to here
- return MYSQL_TYPE_DATETIME;
- }
- }
- // Get a temporal value to compare to another Item
- longlong val_temporal_packed(const Item *other)
- {
- return val_temporal_packed(field_type_for_temporal_comparison(other));
- }
bool get_seconds(ulonglong *sec, ulong *sec_part);
virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date(ltime,fuzzydate); }
@@ -1514,14 +1436,9 @@ public:
static CHARSET_INFO *default_charset();
- /*
- For backward compatibility, to make numeric
- data types return "binary" charset in client-side metadata.
- */
- virtual CHARSET_INFO *charset_for_protocol(void) const
+ CHARSET_INFO *charset_for_protocol(void) const
{
- return cmp_type() == STRING_RESULT ? collation.collation :
- &my_charset_bin;
+ return type_handler()->charset_for_protocol(this);
};
virtual bool walk(Item_processor processor, bool walk_subquery, void *arg)
@@ -1732,22 +1649,33 @@ public:
virtual Item **this_item_addr(THD *thd, Item **addr_arg) { return addr_arg; }
// Row emulation
- virtual uint cols() { return 1; }
+ virtual uint cols() const { return 1; }
virtual Item* element_index(uint i) { return this; }
+ virtual bool element_index_by_name(uint *idx, const LEX_CSTRING &name) const
+ {
+ return true; // Error
+ }
virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c);
+ bool check_type_traditional_scalar(const char *opname) const;
+ bool check_type_scalar(const char *opname) const;
+ bool check_type_or_binary(const char *opname, const Type_handler *handler) const;
+ bool check_type_general_purpose_string(const char *opname) const;
+ bool check_type_can_return_int(const char *opname) const;
+ bool check_type_can_return_real(const char *opname) const;
// It is not row => null inside is impossible
virtual bool null_inside() { return 0; }
// used in row subselects to get value of elements
virtual void bring_value() {}
+ const Type_handler *type_handler_long_or_longlong() const
+ {
+ return Type_handler::type_handler_long_or_longlong(max_char_length());
+ }
+
virtual Field *create_tmp_field(bool group, TABLE *table)
{
- /*
- Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into
- Field_long : make them Field_longlong.
- */
- return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2);
+ return tmp_table_field_from_field_type(table);
}
virtual Item_field *field_for_view_update() { return 0; }
@@ -1850,10 +1778,14 @@ public:
}
virtual Field::geometry_type get_geometry_type() const
{ return Field::GEOM_GEOMETRY; };
+ uint uint_geometry_type() const
+ { return get_geometry_type(); }
+ void set_geometry_type(uint type)
+ {
+ DBUG_ASSERT(0);
+ }
String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
- uint32 max_char_length() const
- { return max_length / collation.collation->mbmaxlen; }
bool too_big_for_varchar() const
{ return max_char_length() > CONVERT_IF_BIGGER_TO_BLOB; }
void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs)
@@ -1950,6 +1882,56 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item)
}
+class Type_geometry_attributes
+{
+ uint m_geometry_type;
+ static const uint m_geometry_type_unknown= Field::GEOM_GEOMETRYCOLLECTION + 1;
+ void copy(const Type_handler *handler, const Type_all_attributes *gattr)
+ {
+ // Ignore implicit NULLs
+ m_geometry_type= handler == &type_handler_geometry ?
+ gattr->uint_geometry_type() :
+ m_geometry_type_unknown;
+ }
+public:
+ Type_geometry_attributes()
+ :m_geometry_type(m_geometry_type_unknown)
+ { }
+ Type_geometry_attributes(const Type_handler *handler,
+ const Type_all_attributes *gattr)
+ :m_geometry_type(m_geometry_type_unknown)
+ {
+ copy(handler, gattr);
+ }
+ void join(const Item *item)
+ {
+ // Ignore implicit NULLs
+ if (m_geometry_type == m_geometry_type_unknown)
+ copy(item->type_handler(), item);
+ else if (item->type_handler() == &type_handler_geometry)
+ {
+ m_geometry_type=
+ Field_geom::geometry_type_merge((Field_geom::geometry_type)
+ m_geometry_type,
+ (Field_geom::geometry_type)
+ item->uint_geometry_type());
+ }
+ }
+ Field::geometry_type get_geometry_type() const
+ {
+ return m_geometry_type == m_geometry_type_unknown ?
+ Field::GEOM_GEOMETRY :
+ (Field::geometry_type) m_geometry_type;
+ }
+ void set_geometry_type(uint type)
+ {
+ DBUG_ASSERT(type <= m_geometry_type_unknown);
+ m_geometry_type= type;
+ }
+};
+
+
+
/**
Compare two Items for List<Item>::add_unique()
*/
@@ -1957,6 +1939,120 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item)
bool cmp_items(Item *a, Item *b);
+/**
+ Array of items, e.g. function or aggerate function arguments.
+*/
+class Item_args
+{
+protected:
+ Item **args, *tmp_arg[2];
+ uint arg_count;
+ void set_arguments(THD *thd, List<Item> &list);
+ bool walk_args(Item_processor processor, bool walk_subquery, void *arg)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->walk(processor, walk_subquery, arg))
+ return true;
+ }
+ return false;
+ }
+ bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
+ void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
+ bool excl_dep_on_table(table_map tab_map)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_table(tab_map))
+ return false;
+ }
+ return true;
+ }
+ bool excl_dep_on_grouping_fields(st_select_lex *sel)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_grouping_fields(sel))
+ return false;
+ }
+ return true;
+ }
+public:
+ Item_args(void)
+ :args(NULL), arg_count(0)
+ { }
+ Item_args(Item *a)
+ :args(tmp_arg), arg_count(1)
+ {
+ args[0]= a;
+ }
+ Item_args(Item *a, Item *b)
+ :args(tmp_arg), arg_count(2)
+ {
+ args[0]= a; args[1]= b;
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c)
+ {
+ arg_count= 0;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))
+ {
+ arg_count= 3;
+ args[0]= a; args[1]= b; args[2]= c;
+ }
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d)
+ {
+ arg_count= 0;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))
+ {
+ arg_count= 4;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d;
+ }
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
+ {
+ arg_count= 5;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))
+ {
+ arg_count= 5;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
+ }
+ }
+ Item_args(THD *thd, List<Item> &list)
+ {
+ set_arguments(thd, list);
+ }
+ Item_args(THD *thd, const Item_args *other);
+ bool alloc_arguments(THD *thd, uint count);
+ void add_argument(Item *item)
+ {
+ args[arg_count++]= item;
+ }
+ inline Item **arguments() const { return args; }
+ inline uint argument_count() const { return arg_count; }
+ inline void remove_arguments() { arg_count=0; }
+};
+
+
+class Item_spvar_args: public Item_args
+{
+ TABLE *m_table;
+public:
+ Item_spvar_args():Item_args(), m_table(NULL) { }
+ ~Item_spvar_args();
+ bool row_create_items(THD *thd, List<Spvar_definition> *list);
+ Field *get_row_field(uint i) const
+ {
+ DBUG_ASSERT(m_table);
+ return m_table->field[i];
+ }
+};
+
+
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -2091,7 +2187,10 @@ public:
done again between subsequent executions of a prepared statement.
*/
if (orig_name)
- name= orig_name;
+ {
+ name.str= orig_name;
+ name.length= strlen(orig_name);
+ }
}
};
@@ -2112,8 +2211,9 @@ protected:
*/
THD *m_thd;
+ bool fix_fields_from_item(THD *thd, Item **, const Item *);
public:
- LEX_STRING m_name;
+ LEX_CSTRING m_name;
public:
#ifndef DBUG_OFF
@@ -2125,10 +2225,10 @@ public:
#endif
public:
- Item_sp_variable(THD *thd, char *sp_var_name_str, uint sp_var_name_length);
+ Item_sp_variable(THD *thd, const LEX_CSTRING *sp_var_name);
public:
- bool fix_fields(THD *thd, Item **);
+ bool fix_fields(THD *thd, Item **)= 0;
double val_real();
longlong val_int();
@@ -2137,12 +2237,12 @@ public:
bool is_null();
public:
- inline void make_field(THD *thd, Send_field *field);
+ void make_field(THD *thd, Send_field *field);
inline bool const_item() const;
inline int save_in_field(Field *field, bool no_conversions);
- inline bool send(Protocol *protocol, String *str);
+ inline bool send(Protocol *protocol, st_value *buffer);
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(m_name.str, arg, VCOL_IMPOSSIBLE);
@@ -2153,17 +2253,6 @@ public:
Item_sp_variable inline implementation.
*****************************************************************************/
-inline void Item_sp_variable::make_field(THD *thd, Send_field *field)
-{
- Item *it= this_item();
-
- if (name)
- it->set_name(thd, name, (uint) strlen(name), system_charset_info);
- else
- it->set_name(thd, m_name.str, (uint) m_name.length, system_charset_info);
- it->make_field(thd, field);
-}
-
inline bool Item_sp_variable::const_item() const
{
return TRUE;
@@ -2174,9 +2263,9 @@ inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions)
return this_item()->save_in_field(field, no_conversions);
}
-inline bool Item_sp_variable::send(Protocol *protocol, String *str)
+inline bool Item_sp_variable::send(Protocol *protocol, st_value *buffer)
{
- return this_item()->send(protocol, str);
+ return this_item()->send(protocol, buffer);
}
@@ -2190,14 +2279,18 @@ class Item_splocal :public Item_sp_variable,
public Rewritable_query_parameter,
public Type_handler_hybrid_field_type
{
+protected:
uint m_var_idx;
Type m_type;
+
+ bool append_value_for_log(THD *thd, String *str);
public:
- Item_splocal(THD *thd, const LEX_STRING &sp_var_name, uint sp_var_idx,
+ Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name, uint sp_var_idx,
enum_field_types sp_var_type,
uint pos_in_q= 0, uint len_in_q= 0);
+ bool fix_fields(THD *, Item **);
Item *this_item();
const Item *this_item() const;
Item **this_item_addr(THD *thd, Item **);
@@ -2205,17 +2298,17 @@ public:
virtual void print(String *str, enum_query_type query_type);
public:
- inline const LEX_STRING *my_name() const;
+ inline const LEX_CSTRING *my_name() const;
inline uint get_var_idx() const;
inline enum Type type() const;
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+ uint cols() const { return this_item()->cols(); }
+ Item* element_index(uint i) { return this_item()->element_index(i); }
+ Item** addr(uint i) { return this_item()->addr(i); }
+ bool check_cols(uint c);
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
@@ -2232,13 +2325,108 @@ public:
bool append_for_log(THD *thd, String *str);
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
+
+ /*
+ Override the inherited create_field_for_create_select(),
+ because we want to preserve the exact data type for:
+ DECLARE a1 INT;
+ DECLARE a2 TYPE OF t1.a2;
+ CREATE TABLE t1 AS SELECT a1, a2;
+ The inherited implementation would create a column
+ based on result_type(), which is less exact.
+ */
+ Field *create_field_for_create_select(TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
};
+
+class Item_splocal_row: public Item_splocal
+{
+public:
+ Item_splocal_row(THD *thd, const LEX_CSTRING *sp_var_name,
+ uint sp_var_idx, uint pos_in_q, uint len_in_q)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ pos_in_q, len_in_q)
+ {
+ set_handler(&type_handler_row);
+ }
+ enum Type type() const { return ROW_ITEM; }
+};
+
+
+/**
+ An Item_splocal variant whose data type becomes known only at
+ sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE".
+*/
+class Item_splocal_with_delayed_data_type: public Item_splocal
+{
+public:
+ Item_splocal_with_delayed_data_type(THD *thd,
+ const LEX_CSTRING *sp_var_name,
+ uint sp_var_idx,
+ uint pos_in_q, uint len_in_q)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ pos_in_q, len_in_q)
+ { }
+};
+
+
+/**
+ SP variables that are fields of a ROW.
+ DELCARE r ROW(a INT,b INT);
+ SELECT r.a; -- This is handled by Item_splocal_row_field
+*/
+class Item_splocal_row_field :public Item_splocal
+{
+protected:
+ LEX_CSTRING m_field_name;
+ uint m_field_idx;
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+public:
+ Item_splocal_row_field(THD *thd,
+ const LEX_CSTRING *sp_var_name,
+ const LEX_CSTRING *sp_field_name,
+ uint sp_var_idx, uint sp_field_idx,
+ enum_field_types sp_var_type,
+ uint pos_in_q= 0, uint len_in_q= 0)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, sp_var_type,
+ pos_in_q, len_in_q),
+ m_field_name(*sp_field_name),
+ m_field_idx(sp_field_idx)
+ { }
+ bool fix_fields(THD *thd, Item **);
+ Item *this_item();
+ const Item *this_item() const;
+ Item **this_item_addr(THD *thd, Item **);
+ bool append_for_log(THD *thd, String *str);
+ void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_splocal_row_field_by_name :public Item_splocal_row_field
+{
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+public:
+ Item_splocal_row_field_by_name(THD *thd,
+ const LEX_CSTRING *sp_var_name,
+ const LEX_CSTRING *sp_field_name,
+ uint sp_var_idx,
+ enum_field_types sp_var_type,
+ uint pos_in_q= 0, uint len_in_q= 0)
+ :Item_splocal_row_field(thd, sp_var_name, sp_field_name,
+ sp_var_idx, 0 /* field index will be set later */,
+ sp_var_type, pos_in_q, len_in_q)
+ { }
+ bool fix_fields(THD *thd, Item **it);
+ void print(String *str, enum_query_type query_type);
+};
+
+
/*****************************************************************************
Item_splocal inline implementation.
*****************************************************************************/
-inline const LEX_STRING *Item_splocal::my_name() const
+inline const LEX_CSTRING *Item_splocal::my_name() const
{
return &m_name;
}
@@ -2263,13 +2451,13 @@ public:
Item_case_expr(THD *thd, uint case_expr_id);
public:
+ bool fix_fields(THD *thd, Item **);
Item *this_item();
const Item *this_item() const;
Item **this_item_addr(THD *thd, Item **);
inline enum Type type() const;
- inline Item_result result_type() const;
- enum_field_types field_type() const { return this_item()->field_type(); }
+ const Type_handler *type_handler() const { return this_item()->type_handler(); }
public:
/*
@@ -2293,12 +2481,6 @@ inline enum Item::Type Item_case_expr::type() const
return this_item()->type();
}
-inline Item_result Item_case_expr::result_type() const
-{
- return this_item()->result_type();
-}
-
-
/*
NAME_CONST(given_name, const_value).
This 'function' has all properties of the supplied const_value (which is
@@ -2331,14 +2513,9 @@ public:
bool is_null();
virtual void print(String *str, enum_query_type query_type);
- enum_field_types field_type() const
- {
- return value_item->field_type();
- }
-
- Item_result result_type() const
+ const Type_handler *type_handler() const
{
- return value_item->result_type();
+ return value_item->type_handler();
}
bool const_item() const
@@ -2351,9 +2528,9 @@ public:
return value_item->save_in_field(field, no_conversions);
}
- bool send(Protocol *protocol, String *str)
+ bool send(Protocol *protocol, st_value *buffer)
{
- return value_item->send(protocol, str);
+ return value_item->send(protocol, buffer);
}
bool check_vcol_func_processor(void *arg)
{
@@ -2415,13 +2592,13 @@ protected:
*/
const char *orig_db_name;
const char *orig_table_name;
- const char *orig_field_name;
+ LEX_CSTRING orig_field_name;
public:
Name_resolution_context *context;
const char *db_name;
const char *table_name;
- const char *field_name;
+ LEX_CSTRING field_name;
bool alias_name_used; /* true if item was resolved against alias */
/*
Cached value of index for this field in table->field array, used by prep.
@@ -2451,9 +2628,9 @@ public:
bool can_be_depended;
Item_ident(THD *thd, Name_resolution_context *context_arg,
const char *db_name_arg, const char *table_name_arg,
- const char *field_name_arg);
+ const LEX_CSTRING *field_name_arg);
Item_ident(THD *thd, Item_ident *item);
- Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_arg);
+ Item_ident(THD *thd, TABLE_LIST *view_arg, const LEX_CSTRING *field_name_arg);
const char *full_name() const;
void cleanup();
st_select_lex *get_depended_from() const;
@@ -2482,17 +2659,20 @@ public:
Item_ident_for_show(THD *thd, Field *par_field, const char *db_arg,
const char *table_name_arg):
Item(thd), field(par_field), db_name(db_arg), table_name(table_name_arg)
- {}
-
+ {
+ Type_std_attributes::set(par_field);
+ }
enum Type type() const { return FIELD_ITEM; }
double val_real() { return field->val_real(); }
longlong val_int() { return field->val_int(); }
String *val_str(String *str) { return field->val_str(str); }
my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); }
void make_field(THD *thd, Send_field *tmp_field);
- CHARSET_INFO *charset_for_protocol(void) const
- { return field->charset_for_protocol(); }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const
+ {
+ const Type_handler *handler= field->type_handler();
+ return handler->type_handler_for_item_field();
+ }
Item* get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_ident_for_show>(thd, mem_root, this); }
};
@@ -2514,7 +2694,7 @@ public:
bool any_privileges;
Item_field(THD *thd, Name_resolution_context *context_arg,
const char *db_arg,const char *table_name_arg,
- const char *field_name_arg);
+ const LEX_CSTRING *field_name_arg);
/*
Constructor needed to process subselect with temporary tables (see Item)
*/
@@ -2544,7 +2724,7 @@ public:
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool is_null_result();
- bool send(Protocol *protocol, String *str_arg);
+ bool send(Protocol *protocol, st_value *buffer);
void reset_field(Field *f);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
@@ -2554,18 +2734,22 @@ public:
fast_field_copier setup_fast_field_copier(Field *field);
table_map used_tables() const;
table_map all_used_tables() const;
- enum Item_result result_type () const
+ const Type_handler *type_handler() const
{
- return field->result_type();
+ const Type_handler *handler= field->type_handler();
+ return handler->type_handler_for_item_field();
}
- Item_result cast_to_int_type() const
+ const Type_handler *cast_to_int_type_handler() const
{
- return field->cmp_type();
+ return field->type_handler()->cast_to_int_type_handler();
}
- enum_field_types field_type() const
+ const Type_handler *real_type_handler() const
{
- return field->type();
+ if (field->is_created_from_null_item)
+ return &type_handler_null;
+ return field->type_handler();
}
+ TYPELIB *get_typelib() const { return field->get_typelib(); }
enum_monotonicity_info get_monotonicity_info() const
{
return MONOTONIC_STRICT_INCREASING;
@@ -2640,9 +2824,9 @@ public:
if (field && (field->unireg_check == Field::NEXT_NUMBER))
{
// Auto increment fields are unsupported
- return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF | VCOL_AUTO_INC);
+ return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF | VCOL_AUTO_INC);
}
- return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF);
+ return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF);
}
void cleanup();
Item_equal *get_item_equal() { return item_equal; }
@@ -2650,7 +2834,7 @@ public:
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
Item *replace_equal_field(THD *thd, uchar *arg);
- inline uint32 max_disp_length() { return field->max_display_length(); }
+ uint32 max_display_length() const { return field->max_display_length(); }
Item_field *field_for_view_update() { return this; }
int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
@@ -2677,14 +2861,44 @@ public:
DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY);
return field->get_geometry_type();
}
- CHARSET_INFO *charset_for_protocol(void) const
- { return field->charset_for_protocol(); }
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
};
+/**
+ Item_field for the ROW data type
+*/
+class Item_field_row: public Item_field,
+ public Item_spvar_args
+{
+public:
+ Item_field_row(THD *thd, Field *field)
+ :Item_field(thd, field),
+ Item_spvar_args()
+ { }
+
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_field_row>(thd, mem_root, this); }
+
+ const Type_handler *type_handler() const { return &type_handler_row; }
+ uint cols() const { return arg_count; }
+ bool element_index_by_name(uint *idx, const LEX_CSTRING &name) const;
+ Item* element_index(uint i) { return arg_count ? args[i] : this; }
+ Item** addr(uint i) { return arg_count ? args + i : NULL; }
+ bool check_cols(uint c)
+ {
+ if (cols() != c)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), c);
+ return true;
+ }
+ return false;
+ }
+};
+
+
/*
@brief
Item_temptable_field is the same as Item_field, except that print()
@@ -2728,12 +2942,13 @@ public:
class Item_null :public Item_basic_constant
{
public:
- Item_null(THD *thd, char *name_par=0, CHARSET_INFO *cs= &my_charset_bin):
+ Item_null(THD *thd, const char *name_par=0, CHARSET_INFO *cs= &my_charset_bin):
Item_basic_constant(thd)
{
maybe_null= null_value= TRUE;
max_length= 0;
- name= name_par ? name_par : (char*) "NULL";
+ name.str= name_par ? name_par : "NULL";
+ name.length= strlen(name.str);
fixed= 1;
collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
}
@@ -2745,9 +2960,8 @@ public:
my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
- bool send(Protocol *protocol, String *str);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
+ bool send(Protocol *protocol, st_value *buffer);
+ const Type_handler *type_handler() const { return &type_handler_null; }
bool basic_const_item() const { return 1; }
Item *clone_item(THD *thd);
bool is_null() { return 1; }
@@ -2795,7 +3009,8 @@ public:
class Item_param :public Item_basic_value,
private Settable_routine_parameter,
public Rewritable_query_parameter,
- public Type_handler_hybrid_field_type
+ public Type_handler_hybrid_field_type,
+ public Type_geometry_attributes
{
/*
NO_VALUE is a special value meaning that the parameter has not been
@@ -2922,14 +3137,17 @@ public:
MYSQL_TIME time;
} value;
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+
+ Field::geometry_type get_geometry_type() const
+ { return Type_geometry_attributes::get_geometry_type(); };
+
+ void set_geometry_type(uint type)
+ { Type_geometry_attributes::set_geometry_type(type); }
- Item_param(THD *thd, uint pos_in_query_arg);
+ Item_param(THD *thd, const LEX_CSTRING *name_arg,
+ uint pos_in_query_arg, uint len_in_query_arg);
enum Type type() const
{
@@ -3054,12 +3272,21 @@ public:
{ max_length=length; fixed= 1; unsigned_flag= 1; }
Item_int(THD *thd, const char *str_arg,longlong i,uint length):
Item_num(thd), value(i)
- { max_length=length; name=(char*) str_arg; fixed= 1; }
+ {
+ max_length=length;
+ name.str= str_arg; name.length= safe_strlen(name.str);
+ fixed= 1;
+ }
Item_int(THD *thd, const char *str_arg, uint length=64);
enum Type type() const { return INT_ITEM; }
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
+ Field *create_field_for_create_select(TABLE *table)
+ { return tmp_table_field_from_field_type(table); }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
+ longlong val_int_min() const { DBUG_ASSERT(fixed == 1); return value; }
double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
@@ -3139,8 +3366,7 @@ public:
Item_decimal(THD *thd, const uchar *bin, int precision, int scale);
enum Type type() const { return DECIMAL_ITEM; }
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
longlong val_int();
double val_real();
String *val_str(String*);
@@ -3160,16 +3386,17 @@ public:
class Item_float :public Item_num
{
- char *presentation;
+ const char *presentation;
public:
double value;
Item_float(THD *thd, const char *str_arg, uint length);
Item_float(THD *thd, const char *str, double val_arg, uint decimal_par,
uint length): Item_num(thd), value(val_arg)
{
- presentation= name=(char*) str;
+ presentation= name.str= str;
+ name.length= safe_strlen(str);
decimals=(uint8) decimal_par;
- max_length=length;
+ max_length= length;
fixed= 1;
}
Item_float(THD *thd, double value_par, uint decimal_par):
@@ -3180,7 +3407,7 @@ public:
}
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int()
{
@@ -3295,7 +3522,7 @@ public:
{
str_value.set_or_copy_aligned(str, length, cs);
fix_from_value(dv, Metadata(&str_value));
- set_name(thd, name_par, 0, system_charset_info);
+ set_name(thd, name_par, safe_strlen(name_par), system_charset_info);
}
Item_string(THD *thd, const char *name_par, const char *str, uint length,
CHARSET_INFO *cs, Derivation dv, uint repertoire):
@@ -3303,7 +3530,7 @@ public:
{
str_value.set_or_copy_aligned(str, length, cs);
fix_from_value(dv, Metadata(&str_value, repertoire));
- set_name(thd, name_par, 0, system_charset_info);
+ set_name(thd, name_par, safe_strlen(name_par), system_charset_info);
}
void print_value(String *to) const
{
@@ -3319,8 +3546,7 @@ public:
}
my_decimal *val_decimal(my_decimal *);
int save_in_field(Field *field, bool no_conversions);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const
{
@@ -3331,7 +3557,7 @@ public:
{
return const_charset_converter(thd, tocs, true);
}
- inline void append(char *str, uint length)
+ inline void append(const char *str, uint length)
{
str_value.append(str, length);
max_length= str_value.numchars() * collation.collation->mbmaxlen;
@@ -3366,7 +3592,7 @@ public:
String *check_well_formed_result(bool send_error)
{ return Item::check_well_formed_result(&str_value, send_error); }
- enum_field_types odbc_temporal_literal_type(const LEX_STRING *type_str) const
+ enum_field_types odbc_temporal_literal_type(const LEX_CSTRING *type_str) const
{
/*
If string is a reasonably short pure ASCII string literal,
@@ -3505,7 +3731,10 @@ public:
Item_partition_func_safe_string(thd, name_arg, length_arg, &my_charset_bin),
date_time_field_type(field_type_arg)
{ decimals= 0; }
- enum_field_types field_type() const { return date_time_field_type; }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler::get_handler_by_field_type(date_time_field_type);
+ }
};
@@ -3513,12 +3742,21 @@ class Item_blob :public Item_partition_func_safe_string
{
public:
Item_blob(THD *thd, const char *name_arg, uint length):
- Item_partition_func_safe_string(thd, name_arg, strlen(name_arg), &my_charset_bin)
+ Item_partition_func_safe_string(thd, name_arg, safe_strlen(name_arg), &my_charset_bin)
{ max_length= length; }
enum Type type() const { return TYPE_HOLDER; }
- enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler::blob_type_handler(max_length);
+ }
+ const Type_handler *real_type_handler() const
+ {
+ // Should not be called, Item_blob is used for SHOW purposes only.
+ DBUG_ASSERT(0);
+ return &type_handler_varchar;
+ }
Field *create_field_for_schema(THD *thd, TABLE *table)
- { return tmp_table_field_from_field_type(table, false, true); }
+ { return tmp_table_field_from_field_type(table); }
};
@@ -3535,7 +3773,11 @@ public:
CHARSET_INFO *cs= NULL):
Item_partition_func_safe_string(thd, "", 0,
cs ? cs : &my_charset_utf8_general_ci)
- { name=(char*) header; max_length= length * collation.collation->mbmaxlen; }
+ {
+ name.str= header;
+ name.length= strlen(name.str);
+ max_length= length * collation.collation->mbmaxlen;
+ }
void make_field(THD *thd, Send_field *field);
};
@@ -3550,7 +3792,10 @@ public:
{
unsigned_flag=1;
}
- enum_field_types field_type() const { return int_field_type; }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler::get_handler_by_field_type(int_field_type);
+ }
};
@@ -3572,8 +3817,7 @@ public:
hex_string_init(thd, str, str_length);
}
enum Type type() const { return VARBIN_ITEM; }
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
{
return const_charset_converter(thd, tocs, true);
@@ -3583,7 +3827,7 @@ public:
bool eq(const Item *item, bool binary_cmp) const
{
return item->basic_const_item() && item->type() == type() &&
- item->cast_to_int_type() == cast_to_int_type() &&
+ item->cast_to_int_type_handler() == cast_to_int_type_handler() &&
str_value.bin_eq(&((Item_hex_constant*)item)->str_value);
}
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
@@ -3601,6 +3845,7 @@ public:
Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {}
Item_hex_hybrid(THD *thd, const char *str, uint str_length):
Item_hex_constant(thd, str, str_length) {}
+ uint decimal_precision() const;
double val_real()
{
DBUG_ASSERT(fixed == 1);
@@ -3625,7 +3870,10 @@ public:
field->set_notnull();
return field->store_hex_hybrid(str_value.ptr(), str_value.length());
}
- enum Item_result cast_to_int_type() const { return INT_RESULT; }
+ const Type_handler *cast_to_int_type_handler() const
+ {
+ return &type_handler_longlong;
+ }
void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_hex_hybrid>(thd, mem_root, this); }
@@ -3667,7 +3915,6 @@ public:
return field->store(str_value.ptr(), str_value.length(),
collation.collation);
}
- enum Item_result cast_to_int_type() const { return STRING_RESULT; }
void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_hex_string>(thd, mem_root, this); }
@@ -3707,8 +3954,6 @@ public:
bool const_item() const { return true; }
enum Type type() const { return DATE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- enum Item_result result_type () const { return STRING_RESULT; }
- Item_result cmp_type() const { return TIME_RESULT; }
bool check_partition_func_processor(void *int_arg) {return FALSE;}
@@ -3724,7 +3969,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
int save_in_field(Field *field, bool no_conversions)
- { return save_date_in_field(field); }
+ { return save_date_in_field(field, no_conversions); }
};
@@ -3748,7 +3993,7 @@ public:
*/
maybe_null= !ltime->month || !ltime->day;
}
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
void print(String *str, enum_query_type query_type);
Item *clone_item(THD *thd);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -3769,7 +4014,7 @@ public:
max_length= MIN_TIME_WIDTH + (decimals ? decimals + 1 : 0);
fixed= 1;
}
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ const Type_handler *type_handler() const { return &type_handler_time2; }
void print(String *str, enum_query_type query_type);
Item *clone_item(THD *thd);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -3792,7 +4037,7 @@ public:
// See the comment on maybe_null in Item_date_literal
maybe_null= !ltime->month || !ltime->day;
}
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ const Type_handler *type_handler() const { return &type_handler_datetime2; }
void print(String *str, enum_query_type query_type);
Item *clone_item(THD *thd);
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
@@ -3858,100 +4103,6 @@ public:
};
-/**
- Array of items, e.g. function or aggerate function arguments.
-*/
-class Item_args
-{
-protected:
- Item **args, *tmp_arg[2];
- uint arg_count;
- void set_arguments(THD *thd, List<Item> &list);
- bool walk_args(Item_processor processor, bool walk_subquery, void *arg)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->walk(processor, walk_subquery, arg))
- return true;
- }
- return false;
- }
- bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
- void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
- bool excl_dep_on_table(table_map tab_map)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->const_item())
- continue;
- if (!args[i]->excl_dep_on_table(tab_map))
- return false;
- }
- return true;
- }
- bool excl_dep_on_grouping_fields(st_select_lex *sel)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->const_item())
- continue;
- if (!args[i]->excl_dep_on_grouping_fields(sel))
- return false;
- }
- return true;
- }
-public:
- Item_args(void)
- :args(NULL), arg_count(0)
- { }
- Item_args(Item *a)
- :args(tmp_arg), arg_count(1)
- {
- args[0]= a;
- }
- Item_args(Item *a, Item *b)
- :args(tmp_arg), arg_count(2)
- {
- args[0]= a; args[1]= b;
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c)
- {
- arg_count= 0;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))
- {
- arg_count= 3;
- args[0]= a; args[1]= b; args[2]= c;
- }
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d)
- {
- arg_count= 0;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))
- {
- arg_count= 4;
- args[0]= a; args[1]= b; args[2]= c; args[3]= d;
- }
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
- {
- arg_count= 5;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))
- {
- arg_count= 5;
- args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
- }
- }
- Item_args(THD *thd, List<Item> &list)
- {
- set_arguments(thd, list);
- }
- Item_args(THD *thd, const Item_args *other);
- inline Item **arguments() const { return args; }
- inline uint argument_count() const { return arg_count; }
- inline void remove_arguments() { arg_count=0; }
-};
-
-
class Used_tables_and_const_cache
{
public:
@@ -4021,80 +4172,31 @@ class Item_func_or_sum: public Item_result_field,
public Item_args,
public Used_tables_and_const_cache
{
- bool agg_item_collations(DTCollation &c, const char *name,
- Item **items, uint nitems,
- uint flags, int item_sep);
- bool agg_item_set_converter(const DTCollation &coll, const char *fname,
- Item **args, uint nargs,
- uint flags, int item_sep);
protected:
- /*
- Collect arguments' character sets together.
- We allow to apply automatic character set conversion in some cases.
- The conditions when conversion is possible are:
- - arguments A and B have different charsets
- - A wins according to coercibility rules
- (i.e. a column is stronger than a string constant,
- an explicit COLLATE clause is stronger than a column)
- - character set of A is either superset for character set of B,
- or B is a string constant which can be converted into the
- character set of A without data loss.
-
- If all of the above is true, then it's possible to convert
- B into the character set of A, and then compare according
- to the collation of A.
-
- For functions with more than two arguments:
-
- collect(A,B,C) ::= collect(collect(A,B),C)
-
- Since this function calls THD::change_item_tree() on the passed Item **
- pointers, it is necessary to pass the original Item **'s, not copies.
- Otherwise their values will not be properly restored (see BUG#20769).
- If the items are not consecutive (eg. args[2] and args[5]), use the
- item_sep argument, ie.
-
- agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
- */
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
uint flags, int item_sep)
{
- if (agg_item_collations(c, func_name(), items, nitems, flags, item_sep))
- return true;
-
- return agg_item_set_converter(c, func_name(), items, nitems,
- flags, item_sep);
+ return Type_std_attributes::agg_arg_charsets(c, func_name(),
+ items, nitems,
+ flags, item_sep);
}
- /*
- Aggregate arguments for string result, e.g: CONCAT(a,b)
- - convert to @@character_set_connection if all arguments are numbers
- - allow DERIVATION_NONE
- */
bool agg_arg_charsets_for_string_result(DTCollation &c,
Item **items, uint nitems,
int item_sep= 1)
{
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
- MY_COLL_ALLOW_COERCIBLE_CONV |
- MY_COLL_ALLOW_NUMERIC_CONV;
- return agg_arg_charsets(c, items, nitems, flags, item_sep);
+ return Type_std_attributes::
+ agg_arg_charsets_for_string_result(c, func_name(),
+ items, nitems, item_sep);
}
- /*
- Aggregate arguments for string result, when some comparison
- is involved internally, e.g: REPLACE(a,b,c)
- - convert to @@character_set_connection if all arguments are numbers
- - disallow DERIVATION_NONE
- */
bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c,
Item **items,
uint nitems,
int item_sep= 1)
{
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
- MY_COLL_ALLOW_COERCIBLE_CONV |
- MY_COLL_ALLOW_NUMERIC_CONV |
- MY_COLL_DISALLOW_NONE;
- return agg_arg_charsets(c, items, nitems, flags, item_sep);
+ return Type_std_attributes::
+ agg_arg_charsets_for_string_result_with_comparison(c, func_name(),
+ items, nitems,
+ item_sep);
}
/*
@@ -4106,13 +4208,10 @@ protected:
Item **items, uint nitems,
int item_sep= 1)
{
- uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
- MY_COLL_ALLOW_COERCIBLE_CONV |
- MY_COLL_DISALLOW_NONE;
- return agg_arg_charsets(c, items, nitems, flags, item_sep);
+ return Type_std_attributes::
+ agg_arg_charsets_for_comparison(c, func_name(), items, nitems, item_sep);
}
-
public:
// This method is used by Arg_comparator
bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b)
@@ -4195,7 +4294,7 @@ public:
bool reference_trough_name;
Item_ref(THD *thd, Name_resolution_context *context_arg,
const char *db_arg, const char *table_name_arg,
- const char *field_name_arg):
+ const LEX_CSTRING *field_name_arg):
Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg),
set_properties_only(0), ref(0), reference_trough_name(1) {}
/*
@@ -4213,10 +4312,10 @@ public:
with Bar, and if we have a more broader set of problems like this.
*/
Item_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
- const char *table_name_arg, const char *field_name_arg,
+ const char *table_name_arg, const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg= FALSE);
Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item,
- const char *field_name_arg, bool alias_name_used_arg= FALSE);
+ const LEX_CSTRING *field_name_arg, bool alias_name_used_arg= FALSE);
/* Constructor need to process subselect with temporary tables (see Item) */
Item_ref(THD *thd, Item_ref *item)
@@ -4244,7 +4343,7 @@ public:
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool is_null_result();
- bool send(Protocol *prot, String *tmp);
+ bool send(Protocol *prot, st_value *buffer);
void make_field(THD *thd, Send_field *field);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
@@ -4252,8 +4351,9 @@ public:
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
fast_field_copier setup_fast_field_copier(Field *field)
{ return (*ref)->setup_fast_field_copier(field); }
- enum Item_result result_type () const { return (*ref)->result_type(); }
- enum_field_types field_type() const { return (*ref)->field_type(); }
+ const Type_handler *type_handler() const { return (*ref)->type_handler(); }
+ const Type_handler *real_type_handler() const
+ { return (*ref)->real_type_handler(); }
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
@@ -4291,6 +4391,11 @@ public:
{
return ref ? (*ref)->real_item() : this;
}
+ TYPELIB *get_typelib() const
+ {
+ return ref ? (*ref)->get_typelib() : NULL;
+ }
+
bool walk(Item_processor processor, bool walk_subquery, void *arg)
{
if (ref && *ref)
@@ -4319,7 +4424,7 @@ public:
virtual Ref_Type ref_type() { return REF; }
// Row emulation: forwarding of ROW-related calls to ref
- uint cols()
+ uint cols() const
{
return ref && result_type() == ROW_RESULT ? (*ref)->cols() : 1;
}
@@ -4405,7 +4510,7 @@ class Item_direct_ref :public Item_ref
public:
Item_direct_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
const char *table_name_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg= FALSE):
Item_ref(thd, context_arg, item, table_name_arg,
field_name_arg, alias_name_used_arg)
@@ -4413,7 +4518,7 @@ public:
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
Item_direct_ref(THD *thd, TABLE_LIST *view_arg, Item **item,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
bool alias_name_used_arg= FALSE):
Item_ref(thd, view_arg, item, field_name_arg,
alias_name_used_arg)
@@ -4451,7 +4556,7 @@ class Item_direct_ref_to_ident :public Item_direct_ref
public:
Item_direct_ref_to_ident(THD *thd, Item_ident *item):
Item_direct_ref(thd, item->context, (Item**)&item, item->table_name,
- item->field_name, FALSE)
+ &item->field_name, FALSE)
{
ident= item;
ref= (Item**)&ident;
@@ -4524,7 +4629,7 @@ public:
bool val_bool();
bool is_null();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
@@ -4552,8 +4657,7 @@ public:
orig_item->fix_after_pullout(new_parent, &orig_item);
}
int save_in_field(Field *to, bool no_conversions);
- enum Item_result result_type () const { return orig_item->result_type(); }
- enum_field_types field_type() const { return orig_item->field_type(); }
+ const Type_handler *type_handler() const { return orig_item->type_handler(); }
table_map used_tables() const { return orig_item->used_tables(); }
void update_used_tables()
{
@@ -4572,7 +4676,7 @@ public:
{ return orig_item->field_for_view_update(); }
/* Row emulation: forwarding of ROW-related calls to orig_item */
- uint cols()
+ uint cols() const
{ return result_type() == ROW_RESULT ? orig_item->cols() : 1; }
Item* element_index(uint i)
{ return result_type() == ROW_RESULT ? orig_item->element_index(i) : this; }
@@ -4638,7 +4742,7 @@ public:
Item_direct_view_ref(THD *thd, Name_resolution_context *context_arg,
Item **item,
const char *table_name_arg,
- const char *field_name_arg,
+ LEX_CSTRING *field_name_arg,
TABLE_LIST *view_arg):
Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg),
item_equal(0), view(view_arg),
@@ -4745,7 +4849,7 @@ public:
}
return Item_direct_ref::get_date(ltime, fuzzydate);
}
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
@@ -4799,7 +4903,7 @@ public:
Item_outer_ref(THD *thd, Name_resolution_context *context_arg,
Item_field *outer_field_arg):
Item_direct_ref(thd, context_arg, 0, outer_field_arg->table_name,
- outer_field_arg->field_name),
+ &outer_field_arg->field_name),
outer_ref(outer_field_arg), in_sum_func(0),
found_in_select_list(0), found_in_group_by(0)
{
@@ -4808,7 +4912,7 @@ public:
fixed= 0; /* reset flag set in set_properties() */
}
Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item **item,
- const char *table_name_arg, const char *field_name_arg,
+ const char *table_name_arg, LEX_CSTRING *field_name_arg,
bool alias_name_used_arg):
Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg,
alias_name_used_arg),
@@ -4849,7 +4953,8 @@ protected:
public:
Item_ref_null_helper(THD *thd, Name_resolution_context *context_arg,
Item_in_subselect* master, Item **item,
- const char *table_name_arg, const char *field_name_arg):
+ const char *table_name_arg,
+ const LEX_CSTRING *field_name_arg):
Item_ref(thd, context_arg, item, table_name_arg, field_name_arg),
owner(master) {}
void save_val(Field *to);
@@ -4952,8 +5057,8 @@ protected:
item= i;
null_value=maybe_null=item->maybe_null;
Type_std_attributes::set(item);
- name=item->name;
- set_handler_by_field_type(item->field_type());
+ name= item->name;
+ set_handler(item->type_handler());
fixed= item->fixed;
}
@@ -4979,12 +5084,8 @@ public:
/** All of the subclasses should have the same type tag */
enum Type type() const { return COPY_STR_ITEM; }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
void make_field(THD *thd, Send_field *field) { item->make_field(thd, field); }
table_map used_tables() const { return (table_map) 1L; }
@@ -5239,15 +5340,15 @@ public:
Item *arg;
Item_default_value(THD *thd, Name_resolution_context *context_arg)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(NULL) {}
Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(a) {}
Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(NULL) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
@@ -5258,7 +5359,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param)
{
@@ -5310,7 +5411,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
- bool send(Protocol *protocol, String *buffer);
+ bool send(Protocol *protocol, st_value *buffer);
};
@@ -5330,7 +5431,7 @@ public:
Item *arg;
Item_insert_value(THD *thd, Name_resolution_context *context_arg, Item *a)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
- (const char *)NULL),
+ &null_clex_str),
arg(a) {}
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, Item **);
@@ -5391,7 +5492,7 @@ public:
Item_trigger_field(THD *thd, Name_resolution_context *context_arg,
row_version_type row_ver_arg,
- const char *field_name_arg,
+ const LEX_CSTRING *field_name_arg,
ulong priv, const bool ro)
:Item_field(thd, context_arg,
(const char *)NULL, (const char *)NULL, field_name_arg),
@@ -5477,7 +5578,7 @@ protected:
public:
Item_cache(THD *thd):
Item_basic_constant(thd),
- Type_handler_hybrid_field_type(MYSQL_TYPE_STRING),
+ Type_handler_hybrid_field_type(&type_handler_string),
example(0), cached_field(0),
value_cached(0)
{
@@ -5486,9 +5587,9 @@ public:
null_value= 1;
}
protected:
- Item_cache(THD *thd, enum_field_types field_type_arg):
+ Item_cache(THD *thd, const Type_handler *handler):
Item_basic_constant(thd),
- Type_handler_hybrid_field_type(field_type_arg),
+ Type_handler_hybrid_field_type(handler),
example(0), cached_field(0),
value_cached(0)
{
@@ -5509,15 +5610,9 @@ public:
};
enum Type type() const { return CACHE_ITEM; }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
-
- static Item_cache* get_cache(THD *thd, const Item *item);
- static Item_cache* get_cache(THD *thd, const Item* item, const Item_result type);
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+
virtual void keep_array() {}
virtual void print(String *str, enum_query_type query_type);
bool eq_def(const Field *field)
@@ -5608,16 +5703,15 @@ class Item_cache_int: public Item_cache
protected:
longlong value;
public:
- Item_cache_int(THD *thd): Item_cache(thd, MYSQL_TYPE_LONGLONG),
+ Item_cache_int(THD *thd): Item_cache(thd, &type_handler_longlong),
value(0) {}
- Item_cache_int(THD *thd, enum_field_types field_type_arg):
- Item_cache(thd, field_type_arg), value(0) {}
+ Item_cache_int(THD *thd, const Type_handler *handler):
+ Item_cache(thd, handler), value(0) {}
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return INT_RESULT; }
bool cache_value();
int save_in_field(Field *field, bool no_conversions);
Item *convert_to_basic_const_item(THD *thd);
@@ -5629,7 +5723,7 @@ public:
class Item_cache_temporal: public Item_cache_int
{
public:
- Item_cache_temporal(THD *thd, enum_field_types field_type_arg);
+ Item_cache_temporal(THD *thd, const Type_handler *handler);
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
longlong val_int();
@@ -5639,7 +5733,6 @@ public:
bool cache_value();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
int save_in_field(Field *field, bool no_conversions);
- Item_result cmp_type() const { return TIME_RESULT; }
void store_packed(longlong val_arg, Item *example);
/*
Having a clone_item method tells optimizer that this object
@@ -5657,14 +5750,13 @@ class Item_cache_real: public Item_cache
{
double value;
public:
- Item_cache_real(THD *thd): Item_cache(thd, MYSQL_TYPE_DOUBLE),
+ Item_cache_real(THD *thd): Item_cache(thd, &type_handler_double),
value(0) {}
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return REAL_RESULT; }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -5677,13 +5769,12 @@ class Item_cache_decimal: public Item_cache
protected:
my_decimal decimal_value;
public:
- Item_cache_decimal(THD *thd): Item_cache(thd, MYSQL_TYPE_NEWDECIMAL) {}
+ Item_cache_decimal(THD *thd): Item_cache(thd, &type_handler_newdecimal) {}
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return DECIMAL_RESULT; }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -5699,7 +5790,7 @@ class Item_cache_str: public Item_cache
public:
Item_cache_str(THD *thd, const Item *item):
- Item_cache(thd, item->field_type()), value(0),
+ Item_cache(thd, item->type_handler()), value(0),
is_varbinary(item->type() == FIELD_ITEM &&
Item_cache_str::field_type() == MYSQL_TYPE_VARCHAR &&
!((const Item_field *) item)->field->has_charset())
@@ -5710,7 +5801,6 @@ public:
longlong val_int();
String* val_str(String *);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return STRING_RESULT; }
CHARSET_INFO *charset() const { return value->charset(); };
int save_in_field(Field *field, bool no_conversions);
bool cache_value();
@@ -5792,9 +5882,7 @@ public:
return 0;
};
- enum Item_result result_type() const { return ROW_RESULT; }
-
- uint cols() { return item_count; }
+ uint cols() const { return item_count; }
Item *element_index(uint i) { return values[i]; }
Item **addr(uint i) { return (Item **) (values + i); }
bool check_cols(uint c);
@@ -5826,50 +5914,65 @@ public:
single SP/PS execution.
*/
class Item_type_holder: public Item,
- public Type_handler_hybrid_real_field_type
+ public Type_handler_hybrid_field_type,
+ public Type_geometry_attributes
{
protected:
TYPELIB *enum_set_typelib;
- Field::geometry_type geometry_type;
-
- void get_full_info(Item *item);
-
- /* It is used to count decimal precision in join_types */
- int prev_decimal_int_part;
public:
- Item_type_holder(THD*, Item*);
+ Item_type_holder(THD *thd, Item *item)
+ :Item(thd, item),
+ Type_handler_hybrid_field_type(item->real_type_handler()),
+ enum_set_typelib(0)
+ {
+ DBUG_ASSERT(item->fixed);
+ maybe_null= item->maybe_null;
+ }
+ Item_type_holder(THD *thd,
+ const LEX_CSTRING *name_arg,
+ const Type_handler *handler,
+ const Type_all_attributes *attr,
+ bool maybe_null_arg)
+ :Item(thd),
+ Type_handler_hybrid_field_type(handler),
+ Type_geometry_attributes(handler, attr),
+ enum_set_typelib(attr->get_typelib())
+ {
+ name= *name_arg;
+ Type_std_attributes::set(*attr);
+ maybe_null= maybe_null_arg;
+ }
- enum_field_types field_type() const
- { return Type_handler_hybrid_real_field_type::field_type(); }
- enum_field_types real_field_type() const
- { return Type_handler_hybrid_real_field_type::real_field_type(); }
- enum Item_result result_type () const
+ const Type_handler *type_handler() const
{
- /*
- In 10.1 Item_type_holder::result_type() returned
- Field::result_merge_type(field_type()), which returned STRING_RESULT
- for the BIT data type. In 10.2 it returns INT_RESULT, similar
- to what Field_bit::result_type() does. This should not be
- important because Item_type_holder is a limited purpose Item
- and its result_type() should not be called from outside of
- Item_type_holder. It's called only internally from decimal_int_part()
- from join_types(), to calculate "decimals" of the result data type.
- As soon as we get BIT as one of the joined types, the result field
- type cannot be numeric: it's either BIT, or VARBINARY.
- */
- return Type_handler_hybrid_real_field_type::result_type();
+ const Type_handler *handler= Type_handler_hybrid_field_type::type_handler();
+ return handler->type_handler_for_item_field();
+ }
+ const Type_handler *real_type_handler() const
+ {
+ return Type_handler_hybrid_field_type::type_handler();
}
enum Type type() const { return TYPE_HOLDER; }
+ TYPELIB *get_typelib() const { return enum_set_typelib; }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
- bool join_types(THD *thd, Item *);
- Field *make_field_by_type(TABLE *table);
- static uint32 display_length(Item *item);
- static enum_field_types get_real_type(Item *);
- Field::geometry_type get_geometry_type() const { return geometry_type; };
+ Field *create_tmp_field(bool group, TABLE *table)
+ {
+ return Item_type_holder::real_type_handler()->
+ make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+ }
+ Field::geometry_type get_geometry_type() const
+ {
+ return Type_geometry_attributes::get_geometry_type();
+ }
+ void set_geometry_type(uint type)
+ {
+ Type_geometry_attributes::set_geometry_type(type);
+ }
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index d203efa6305..f4f68e007a0 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -98,34 +98,54 @@ static int cmp_row_type(Item* item1, Item* item2)
/**
Aggregates result types from the array of items.
- SYNOPSIS:
- agg_cmp_type()
- type [out] the aggregated type
- items array of items to aggregate the type from
- nitems number of items in the array
-
- DESCRIPTION
- This function aggregates result types from the array of items. Found type
- supposed to be used later for comparison of values of these items.
- Aggregation itself is performed by the item_cmp_type() function.
- @param[out] type the aggregated type
- @param items array of items to aggregate the type from
- @param nitems number of items in the array
-
- @retval
- 1 type incompatibility has been detected
- @retval
- 0 otherwise
+ This method aggregates comparison handler from the array of items.
+ The result handler is used later for comparison of values of these items.
+
+ aggregate_for_comparison()
+ funcname the function or operator name,
+ for error reporting
+ items array of items to aggregate the type from
+ nitems number of items in the array
+ int_uint_as_dec what to do when comparing INT to UINT:
+ set the comparison handler to decimal or int.
+
+ @retval true type incompatibility has been detected
+ @retval false otherwise
*/
-static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
+bool
+Type_handler_hybrid_field_type::aggregate_for_comparison(const char *funcname,
+ Item **items,
+ uint nitems,
+ bool int_uint_as_dec)
{
uint unsigned_count= items[0]->unsigned_flag;
- type[0]= items[0]->cmp_type();
+ /*
+ Convert sub-type to super-type (e.g. DATE to DATETIME, INT to BIGINT, etc).
+ Otherwise Predicant_to_list_comparator will treat sub-types of the same
+ super-type as different data types and won't be able to use bisection in
+ many cases.
+ */
+ set_handler(items[0]->type_handler()->type_handler_for_comparison());
for (uint i= 1 ; i < nitems ; i++)
{
unsigned_count+= items[i]->unsigned_flag;
- type[0]= item_cmp_type(type[0], items[i]);
+ if (aggregate_for_comparison(items[i]->type_handler()->
+ type_handler_for_comparison()))
+ {
+ /*
+ For more precise error messages if aggregation failed on the first pair
+ {items[0],items[1]}, use the name of items[0]->data_handler().
+ Otherwise use the name of this->type_handler(), which is already a
+ result of aggregation for items[0]..items[i-1].
+ */
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ i == 1 ? items[0]->type_handler()->name().ptr() :
+ type_handler()->name().ptr(),
+ items[i]->type_handler()->name().ptr(),
+ funcname);
+ return true;
+ }
/*
When aggregating types of two row expressions we have to check
that they have the same cardinality and that each component
@@ -133,100 +153,21 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
the signature of the corresponding component of the second row
expression.
*/
- if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
- return 1; // error found: invalid usage of rows
+ if (cmp_type() == ROW_RESULT && cmp_row_type(items[0], items[i]))
+ return true; // error found: invalid usage of rows
}
/**
If all arguments are of INT type but have different unsigned_flag values,
switch to DECIMAL_RESULT.
*/
- if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0)
- type[0]= DECIMAL_RESULT;
+ if (int_uint_as_dec &&
+ cmp_type() == INT_RESULT &&
+ unsigned_count != nitems && unsigned_count != 0)
+ set_handler(&type_handler_newdecimal);
return 0;
}
-/**
- @brief Aggregates field types from the array of items.
-
- @param[in] items array of items to aggregate the type from
- @paran[in] nitems number of items in the array
- @param[in] treat_bit_as_number - if BIT should be aggregated to a non-BIT
- counterpart as a LONGLONG number or as a VARBINARY string.
-
- Currently behaviour depends on the function:
- - LEAST/GREATEST treat BIT as VARBINARY when
- aggregating with a non-BIT counterpart.
- Note, UNION also works this way.
-
- - CASE, COALESCE, IF, IFNULL treat BIT as LONGLONG when
- aggregating with a non-BIT counterpart;
-
- This inconsistency may be changed in the future. See MDEV-8867.
-
- Note, independently from "treat_bit_as_number":
- - a single BIT argument gives BIT as a result
- - two BIT couterparts give BIT as a result
-
- @details This function aggregates field types from the array of items.
- Found type is supposed to be used later as the result field type
- of a multi-argument function.
- Aggregation itself is performed by the Field::field_type_merge()
- function.
-
- @note The term "aggregation" is used here in the sense of inferring the
- result type of a function from its argument types.
-
- @return aggregated field type.
-*/
-
-enum_field_types agg_field_type(Item **items, uint nitems,
- bool treat_bit_as_number)
-{
- uint i;
- if (!nitems || items[0]->result_type() == ROW_RESULT)
- {
- DBUG_ASSERT(0);
- return MYSQL_TYPE_NULL;
- }
- enum_field_types res= items[0]->field_type();
- uint unsigned_count= items[0]->unsigned_flag;
- for (i= 1 ; i < nitems ; i++)
- {
- enum_field_types cur= items[i]->field_type();
- if (treat_bit_as_number &&
- ((res == MYSQL_TYPE_BIT) ^ (cur == MYSQL_TYPE_BIT)))
- {
- if (res == MYSQL_TYPE_BIT)
- res= MYSQL_TYPE_LONGLONG; // BIT + non-BIT
- else
- cur= MYSQL_TYPE_LONGLONG; // non-BIT + BIT
- }
- res= Field::field_type_merge(res, cur);
- unsigned_count+= items[i]->unsigned_flag;
- }
- switch (res) {
- case MYSQL_TYPE_TINY:
- case MYSQL_TYPE_SHORT:
- case MYSQL_TYPE_LONG:
- case MYSQL_TYPE_LONGLONG:
- case MYSQL_TYPE_INT24:
- case MYSQL_TYPE_YEAR:
- case MYSQL_TYPE_BIT:
- if (unsigned_count != 0 && unsigned_count != nitems)
- {
- /*
- If all arguments are of INT-alike type but have different
- unsigned_flag, then convert to DECIMAL.
- */
- return MYSQL_TYPE_NEWDECIMAL;
- }
- default:
- break;
- }
- return res;
-}
-
/*
Collects different types for comparison of first item with each other items
@@ -522,78 +463,6 @@ void Item_bool_rowready_func2::fix_length_and_dec()
}
-int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
-{
- owner= item;
- func= comparator_matrix[type]
- [is_owner_equal_func()];
-
- switch (type) {
- case TIME_RESULT:
- m_compare_collation= &my_charset_numeric;
- break;
- case ROW_RESULT:
- {
- uint n= (*a)->cols();
- if (n != (*b)->cols())
- {
- my_error(ER_OPERAND_COLUMNS, MYF(0), n);
- comparators= 0;
- return 1;
- }
- if (!(comparators= new Arg_comparator[n]))
- return 1;
- for (uint i=0; i < n; i++)
- {
- if ((*a)->element_index(i)->cols() != (*b)->element_index(i)->cols())
- {
- my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
- return 1;
- }
- if (comparators[i].set_cmp_func(owner, (*a)->addr(i),
- (*b)->addr(i), set_null))
- return 1;
- }
- break;
- }
- case INT_RESULT:
- {
- if (func == &Arg_comparator::compare_int_signed)
- {
- if ((*a)->unsigned_flag)
- func= (((*b)->unsigned_flag)?
- &Arg_comparator::compare_int_unsigned :
- &Arg_comparator::compare_int_unsigned_signed);
- else if ((*b)->unsigned_flag)
- func= &Arg_comparator::compare_int_signed_unsigned;
- }
- else if (func== &Arg_comparator::compare_e_int)
- {
- if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
- func= &Arg_comparator::compare_e_int_diff_signedness;
- }
- break;
- }
- case STRING_RESULT:
- case DECIMAL_RESULT:
- break;
- case REAL_RESULT:
- {
- if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC)
- {
- precision= 5 / log_10[MY_MAX((*a)->decimals, (*b)->decimals) + 1];
- if (func == &Arg_comparator::compare_real)
- func= &Arg_comparator::compare_real_fixed;
- else if (func == &Arg_comparator::compare_e_real)
- func= &Arg_comparator::compare_e_real_fixed;
- }
- break;
- }
- }
- return 0;
-}
-
-
/**
Prepare the comparator (set the comparison function) for comparing
items *a1 and *a2 in the context of 'type'.
@@ -610,14 +479,62 @@ int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
Item **a1, Item **a2)
{
- THD *thd= current_thd;
owner= owner_arg;
set_null= set_null && owner_arg;
a= a1;
b= a2;
- m_compare_type= item_cmp_type(*a1, *a2);
+ Item *tmp_args[2]= {*a1, *a2};
+ Type_handler_hybrid_field_type tmp;
+ if (tmp.aggregate_for_comparison(owner_arg->func_name(), tmp_args, 2, false))
+ {
+ DBUG_ASSERT(current_thd->is_error());
+ return 1;
+ }
+ m_compare_handler= tmp.type_handler();
+ return m_compare_handler->set_comparator_func(this);
+}
+
+
+bool Arg_comparator::set_cmp_func_for_row_arguments()
+{
+ uint n= (*a)->cols();
+ if (n != (*b)->cols())
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), n);
+ comparators= 0;
+ return true;
+ }
+ if (!(comparators= new Arg_comparator[n]))
+ return true;
+ for (uint i=0; i < n; i++)
+ {
+ if ((*a)->element_index(i)->cols() != (*b)->element_index(i)->cols())
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
+ return true;
+ }
+ if (comparators[i].set_cmp_func(owner, (*a)->addr(i),
+ (*b)->addr(i), set_null))
+ return true;
+ }
+ return false;
+}
- if (m_compare_type == STRING_RESULT &&
+
+bool Arg_comparator::set_cmp_func_row()
+{
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_row :
+ &Arg_comparator::compare_row;
+ return set_cmp_func_for_row_arguments();
+}
+
+
+bool Arg_comparator::set_cmp_func_string()
+{
+ THD *thd= current_thd;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_string :
+ &Arg_comparator::compare_string;
+ if (compare_type() == STRING_RESULT &&
(*a)->result_type() == STRING_RESULT &&
(*b)->result_type() == STRING_RESULT)
{
@@ -626,30 +543,69 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
generated item, like in natural join
*/
if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b))
- return 1;
+ return true;
}
+ a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
+ b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
+ return false;
+}
- if (m_compare_type == TIME_RESULT)
+
+bool Arg_comparator::set_cmp_func_time()
+{
+ m_compare_collation= &my_charset_numeric;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_time :
+ &Arg_comparator::compare_time;
+ return false;
+}
+
+
+bool Arg_comparator::set_cmp_func_datetime()
+{
+ m_compare_collation= &my_charset_numeric;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
+ &Arg_comparator::compare_datetime;
+ return false;
+}
+
+
+bool Arg_comparator::set_cmp_func_int()
+{
+ THD *thd= current_thd;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_int :
+ &Arg_comparator::compare_int_signed;
+ if ((*a)->field_type() == MYSQL_TYPE_YEAR &&
+ (*b)->field_type() == MYSQL_TYPE_YEAR)
{
- enum_field_types f_type= a[0]->field_type_for_temporal_comparison(b[0]);
- if (f_type == MYSQL_TYPE_TIME)
- {
- func= is_owner_equal_func() ? &Arg_comparator::compare_e_time :
- &Arg_comparator::compare_time;
- }
- else
- {
- func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
- &Arg_comparator::compare_datetime;
- }
- return 0;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
+ &Arg_comparator::compare_datetime;
+ }
+ else if (func == &Arg_comparator::compare_int_signed)
+ {
+ if ((*a)->unsigned_flag)
+ func= (((*b)->unsigned_flag)?
+ &Arg_comparator::compare_int_unsigned :
+ &Arg_comparator::compare_int_unsigned_signed);
+ else if ((*b)->unsigned_flag)
+ func= &Arg_comparator::compare_int_signed_unsigned;
+ }
+ else if (func== &Arg_comparator::compare_e_int)
+ {
+ if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
+ func= &Arg_comparator::compare_e_int_diff_signedness;
}
+ a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
+ b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
+ return false;
+}
- if (m_compare_type == REAL_RESULT &&
- (((*a)->result_type() == DECIMAL_RESULT && !(*a)->const_item() &&
+
+bool Arg_comparator::set_cmp_func_real()
+{
+ if ((((*a)->result_type() == DECIMAL_RESULT && !(*a)->const_item() &&
(*b)->result_type() == STRING_RESULT && (*b)->const_item()) ||
- ((*b)->result_type() == DECIMAL_RESULT && !(*b)->const_item() &&
- (*a)->result_type() == STRING_RESULT && (*a)->const_item())))
+ ((*b)->result_type() == DECIMAL_RESULT && !(*b)->const_item() &&
+ (*a)->result_type() == STRING_RESULT && (*a)->const_item())))
{
/*
<non-const decimal expression> <cmp> <const string expression>
@@ -658,21 +614,35 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
Do comparison as decimal rather than float, in order not to lose precision.
*/
- m_compare_type= DECIMAL_RESULT;
+ m_compare_handler= &type_handler_newdecimal;
+ return set_cmp_func_decimal();
}
- if (m_compare_type == INT_RESULT &&
- (*a)->field_type() == MYSQL_TYPE_YEAR &&
- (*b)->field_type() == MYSQL_TYPE_YEAR)
- {
- m_compare_type= TIME_RESULT;
- func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
- &Arg_comparator::compare_datetime;
- }
+ THD *thd= current_thd;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_real :
+ &Arg_comparator::compare_real;
+ if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC)
+ {
+ precision= 5 / log_10[MY_MAX((*a)->decimals, (*b)->decimals) + 1];
+ if (func == &Arg_comparator::compare_real)
+ func= &Arg_comparator::compare_real_fixed;
+ else if (func == &Arg_comparator::compare_e_real)
+ func= &Arg_comparator::compare_e_real_fixed;
+ }
+ a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
+ b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
+ return false;
+}
+
- a= cache_converted_constant(thd, a, &a_cache, m_compare_type);
- b= cache_converted_constant(thd, b, &b_cache, m_compare_type);
- return set_compare_func(owner_arg, m_compare_type);
+bool Arg_comparator::set_cmp_func_decimal()
+{
+ THD *thd= current_thd;
+ func= is_owner_equal_func() ? &Arg_comparator::compare_e_decimal :
+ &Arg_comparator::compare_decimal;
+ a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
+ b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
+ return false;
}
@@ -695,18 +665,22 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
Item **cache_item,
- Item_result type)
+ const Type_handler *handler)
{
/*
+ get_datetime_value creates Item_cache internally when comparing
+ values for the first row.
+ Arg_comparator::cache_converted_constant() is never called for TIME_RESULT.
+ */
+ DBUG_ASSERT(handler->cmp_type() != TIME_RESULT);
+ /*
Don't need cache if doing context analysis only.
- Also, get_datetime_value creates Item_cache internally.
- Unless fixed, we should not do it here.
*/
if (!thd_arg->lex->is_ps_or_view_context_analysis() &&
- (*value)->const_item() && type != (*value)->result_type() &&
- type != TIME_RESULT)
+ (*value)->const_item() &&
+ handler->cmp_type() != (*value)->cmp_type())
{
- Item_cache *cache= Item_cache::get_cache(thd_arg, *value, type);
+ Item_cache *cache= handler->Item_get_cache(thd_arg, *value);
cache->setup(thd_arg, *value);
*cache_item= cache;
return cache_item;
@@ -760,8 +734,8 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
{
if (!thd)
thd= current_thd;
-
- Item_cache_temporal *cache= new (thd->mem_root) Item_cache_temporal(thd, f_type);
+ const Type_handler *h= Type_handler::get_handler_by_field_type(f_type);
+ Item_cache_temporal *cache= new (thd->mem_root) Item_cache_temporal(thd, h);
cache->store_packed(value, item);
*cache_arg= cache;
*item_arg= cache_arg;
@@ -1267,7 +1241,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
args[0]= ((Item_in_subselect *)args[1])->left_expr;
}
if ((!(*ref0)->fixed && (*ref0)->fix_fields(thd, ref0)) ||
- (!cache && !(cache= Item_cache::get_cache(thd, *ref0))))
+ (!cache && !(cache= (*ref0)->get_cache(thd))))
DBUG_RETURN(1);
/*
During fix_field() expression could be substituted.
@@ -2057,9 +2031,7 @@ void Item_func_between::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_func_between::fix_length_and_dec()
{
- THD *thd= current_thd;
max_length= 1;
- compare_as_dates= 0;
/*
As some compare functions are generated after sql_yacc,
@@ -2067,24 +2039,19 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
- if (agg_cmp_type(&m_compare_type, args, 3))
+ if (m_comparator.aggregate_for_comparison(Item_func_between::func_name(),
+ args, 3, true))
+ {
+ DBUG_ASSERT(current_thd->is_error());
return;
+ }
- if (m_compare_type == STRING_RESULT &&
- agg_arg_charsets_for_comparison(cmp_collation, args, 3))
- return;
+ m_comparator.type_handler()->Item_func_between_fix_length_and_dec(this);
+}
- /*
- When comparing as date/time, we need to convert non-temporal values
- (e.g. strings) to MYSQL_TIME. get_datetime_value() does it
- automatically when one of the operands is a date/time. But here we
- may need to compare two strings as dates (str1 BETWEEN str2 AND date).
- For this to work, we need to know what date/time type we compare
- strings as.
- */
- if (m_compare_type == TIME_RESULT)
- compare_as_dates= find_date_time_item(args, 3, 0);
+bool Item_func_between::fix_length_and_dec_numeric(THD *thd)
+{
/* See the comment about the similar block in Item_bool_func2 */
if (args[0]->real_item()->type() == FIELD_ITEM &&
!thd->lex->is_ps_or_view_context_analysis())
@@ -2096,145 +2063,144 @@ void Item_func_between::fix_length_and_dec()
const bool cvt_arg1= convert_const_to_int(thd, field_item, &args[1]);
const bool cvt_arg2= convert_const_to_int(thd, field_item, &args[2]);
if (cvt_arg1 && cvt_arg2)
- m_compare_type= INT_RESULT; // Works for all types.
+ {
+ // Works for all types
+ m_comparator.set_handler(&type_handler_longlong);
+ }
}
}
+ return false;
}
-longlong Item_func_between::val_int()
+longlong Item_func_between::val_int_cmp_temporal()
{
- DBUG_ASSERT(fixed == 1);
-
- switch (m_compare_type) {
- case TIME_RESULT:
- {
- THD *thd= current_thd;
- longlong value, a, b;
- Item *cache, **ptr;
- bool value_is_null, a_is_null, b_is_null;
+ THD *thd= current_thd;
+ longlong value, a, b;
+ Item *cache, **ptr;
+ bool value_is_null, a_is_null, b_is_null;
- ptr= &args[0];
- enum_field_types f_type= field_type_for_temporal_comparison(compare_as_dates);
- value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null);
- if (ptr != &args[0])
- thd->change_item_tree(&args[0], *ptr);
+ ptr= &args[0];
+ enum_field_types f_type= m_comparator.type_handler()->field_type();
+ value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null);
+ if (ptr != &args[0])
+ thd->change_item_tree(&args[0], *ptr);
- if ((null_value= value_is_null))
- return 0;
+ if ((null_value= value_is_null))
+ return 0;
- ptr= &args[1];
- a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null);
- if (ptr != &args[1])
- thd->change_item_tree(&args[1], *ptr);
+ ptr= &args[1];
+ a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null);
+ if (ptr != &args[1])
+ thd->change_item_tree(&args[1], *ptr);
+
+ ptr= &args[2];
+ b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null);
+ if (ptr != &args[2])
+ thd->change_item_tree(&args[2], *ptr);
+
+ if (!a_is_null && !b_is_null)
+ return (longlong) ((value >= a && value <= b) != negated);
+ if (a_is_null && b_is_null)
+ null_value= true;
+ else if (a_is_null)
+ null_value= value <= b; // not null if false range.
+ else
+ null_value= value >= a;
+ return (longlong) (!null_value && negated);
+}
- ptr= &args[2];
- b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null);
- if (ptr != &args[2])
- thd->change_item_tree(&args[2], *ptr);
- if (!a_is_null && !b_is_null)
- return (longlong) ((value >= a && value <= b) != negated);
- if (a_is_null && b_is_null)
- null_value=1;
- else if (a_is_null)
- null_value= value <= b; // not null if false range.
- else
- null_value= value >= a;
- break;
+longlong Item_func_between::val_int_cmp_string()
+{
+ String *value,*a,*b;
+ value=args[0]->val_str(&value0);
+ if ((null_value=args[0]->null_value))
+ return 0;
+ a= args[1]->val_str(&value1);
+ b= args[2]->val_str(&value2);
+ if (!args[1]->null_value && !args[2]->null_value)
+ return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
+ sortcmp(value,b,cmp_collation.collation) <= 0) !=
+ negated);
+ if (args[1]->null_value && args[2]->null_value)
+ null_value= true;
+ else if (args[1]->null_value)
+ {
+ // Set to not null if false range.
+ null_value= sortcmp(value,b,cmp_collation.collation) <= 0;
}
-
- case STRING_RESULT:
+ else
{
- String *value,*a,*b;
- value=args[0]->val_str(&value0);
- if ((null_value=args[0]->null_value))
- return 0;
- a=args[1]->val_str(&value1);
- b=args[2]->val_str(&value2);
- if (!args[1]->null_value && !args[2]->null_value)
- return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
- sortcmp(value,b,cmp_collation.collation) <= 0) !=
- negated);
- if (args[1]->null_value && args[2]->null_value)
- null_value=1;
- else if (args[1]->null_value)
- {
- // Set to not null if false range.
- null_value= sortcmp(value,b,cmp_collation.collation) <= 0;
- }
- else
- {
- // Set to not null if false range.
- null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
- }
- break;
+ // Set to not null if false range.
+ null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
}
- case INT_RESULT:
+ return (longlong) (!null_value && negated);
+}
+
+
+longlong Item_func_between::val_int_cmp_int()
+{
+ longlong value= args[0]->val_int(), a, b;
+ if ((null_value= args[0]->null_value))
+ return 0; /* purecov: inspected */
+ a= args[1]->val_int();
+ b= args[2]->val_int();
+ if (!args[1]->null_value && !args[2]->null_value)
+ return (longlong) ((value >= a && value <= b) != negated);
+ if (args[1]->null_value && args[2]->null_value)
+ null_value= true;
+ else if (args[1]->null_value)
{
- longlong value=args[0]->val_int(), a, b;
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
- a=args[1]->val_int();
- b=args[2]->val_int();
- if (!args[1]->null_value && !args[2]->null_value)
- return (longlong) ((value >= a && value <= b) != negated);
- if (args[1]->null_value && args[2]->null_value)
- null_value=1;
- else if (args[1]->null_value)
- {
- null_value= value <= b; // not null if false range.
- }
- else
- {
- null_value= value >= a;
- }
- break;
+ null_value= value <= b; // not null if false range.
}
- case DECIMAL_RESULT:
- {
- my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
- a_buf, *a_dec, b_buf, *b_dec;
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
- a_dec= args[1]->val_decimal(&a_buf);
- b_dec= args[2]->val_decimal(&b_buf);
- if (!args[1]->null_value && !args[2]->null_value)
- return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
- my_decimal_cmp(dec, b_dec) <= 0) != negated);
- if (args[1]->null_value && args[2]->null_value)
- null_value=1;
- else if (args[1]->null_value)
- null_value= (my_decimal_cmp(dec, b_dec) <= 0);
- else
- null_value= (my_decimal_cmp(dec, a_dec) >= 0);
- break;
+ else
+ {
+ null_value= value >= a;
}
- case REAL_RESULT:
+ return (longlong) (!null_value && negated);
+}
+
+
+longlong Item_func_between::val_int_cmp_decimal()
+{
+ my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
+ a_buf, *a_dec, b_buf, *b_dec;
+ if ((null_value=args[0]->null_value))
+ return 0; /* purecov: inspected */
+ a_dec= args[1]->val_decimal(&a_buf);
+ b_dec= args[2]->val_decimal(&b_buf);
+ if (!args[1]->null_value && !args[2]->null_value)
+ return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
+ my_decimal_cmp(dec, b_dec) <= 0) != negated);
+ if (args[1]->null_value && args[2]->null_value)
+ null_value= true;
+ else if (args[1]->null_value)
+ null_value= (my_decimal_cmp(dec, b_dec) <= 0);
+ else
+ null_value= (my_decimal_cmp(dec, a_dec) >= 0);
+ return (longlong) (!null_value && negated);
+}
+
+
+longlong Item_func_between::val_int_cmp_real()
+{
+ double value= args[0]->val_real(),a,b;
+ if ((null_value=args[0]->null_value))
+ return 0; /* purecov: inspected */
+ a= args[1]->val_real();
+ b= args[2]->val_real();
+ if (!args[1]->null_value && !args[2]->null_value)
+ return (longlong) ((value >= a && value <= b) != negated);
+ if (args[1]->null_value && args[2]->null_value)
+ null_value= true;
+ else if (args[1]->null_value)
{
- double value= args[0]->val_real(),a,b;
- if ((null_value=args[0]->null_value))
- return 0; /* purecov: inspected */
- a= args[1]->val_real();
- b= args[2]->val_real();
- if (!args[1]->null_value && !args[2]->null_value)
- return (longlong) ((value >= a && value <= b) != negated);
- if (args[1]->null_value && args[2]->null_value)
- null_value=1;
- else if (args[1]->null_value)
- {
- null_value= value <= b; // not null if false range.
- }
- else
- {
- null_value= value >= a;
- }
- break;
+ null_value= value <= b; // not null if false range.
}
- case ROW_RESULT:
- DBUG_ASSERT(0);
- null_value= 1;
- return 0;
+ else
+ {
+ null_value= value >= a;
}
return (longlong) (!null_value && negated);
}
@@ -2252,16 +2218,6 @@ void Item_func_between::print(String *str, enum_query_type query_type)
}
-uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const
-{
- int arg0_int_part= args[0]->decimal_int_part();
- int arg1_int_part= args[1]->decimal_int_part();
- int max_int_part= MY_MAX(arg0_int_part, arg1_int_part);
- int precision= max_int_part + decimals;
- return MY_MIN(precision, DECIMAL_MAX_PRECISION);
-}
-
-
double
Item_func_ifnull::real_op()
{
@@ -2400,91 +2356,6 @@ void Item_func_if::fix_after_pullout(st_select_lex *new_parent, Item **ref)
}
-void Item_func_if::cache_type_info(Item *source)
-{
- Type_std_attributes::set(source);
- set_handler_by_field_type(source->field_type());
- maybe_null= source->maybe_null;
-}
-
-
-void
-Item_func_if::fix_length_and_dec()
-{
- // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
- if (args[1]->type() == NULL_ITEM)
- {
- cache_type_info(args[2]);
- maybe_null= true;
- // 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;
- }
- if (args[2]->type() == NULL_ITEM)
- {
- cache_type_info(args[1]);
- maybe_null= true;
- return;
- }
- Item_func_case_abbreviation2::fix_length_and_dec2(args + 1);
-}
-
-
-double
-Item_func_if::real_op()
-{
- DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_bool() ? args[1] : args[2];
- double value= arg->val_real();
- null_value=arg->null_value;
- return value;
-}
-
-longlong
-Item_func_if::int_op()
-{
- DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_bool() ? args[1] : args[2];
- longlong value=arg->val_int();
- null_value=arg->null_value;
- return value;
-}
-
-String *
-Item_func_if::str_op(String *str)
-{
- DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_bool() ? args[1] : args[2];
- String *res=arg->val_str(str);
- if (res)
- res->set_charset(collation.collation);
- if ((null_value=arg->null_value))
- res= NULL;
- return res;
-}
-
-
-my_decimal *
-Item_func_if::decimal_op(my_decimal *decimal_value)
-{
- DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_bool() ? args[1] : args[2];
- my_decimal *value= arg->val_decimal(decimal_value);
- if ((null_value= arg->null_value))
- value= NULL;
- return value;
-}
-
-
-bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate)
-{
- DBUG_ASSERT(fixed == 1);
- Item *arg= args[0]->val_bool() ? args[1] : args[2];
- return (null_value= arg->get_date_with_conversion(ltime, fuzzydate));
-}
-
-
void Item_func_nullif::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, uint flags)
{
@@ -2690,14 +2561,14 @@ 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]);
+ args[0]->get_cache(thd);
m_cache->setup(thd, args[0]);
m_cache->store(args[0]);
m_cache->set_used_tables(args[0]->used_tables());
thd->change_item_tree(&args[0], m_cache);
thd->change_item_tree(&args[2], m_cache);
}
- set_handler_by_field_type(args[2]->field_type());
+ set_handler(args[2]->type_handler());
collation.set(args[2]->collation);
decimals= args[2]->decimals;
unsigned_flag= args[2]->unsigned_flag;
@@ -2906,8 +2777,10 @@ Item_func_nullif::is_null()
Item_func_case::Item_func_case(THD *thd, List<Item> &list,
Item *first_expr_arg, Item *else_expr_arg):
- Item_func_hybrid_field_type(thd), first_expr_num(-1), else_expr_num(-1),
- left_cmp_type(INT_RESULT), case_item(0), m_found_types(0)
+ Item_func_case_expression(thd),
+ Predicant_to_list_comparator(thd, list.elements/*QQ*/),
+ first_expr_num(-1), else_expr_num(-1),
+ m_found_types(0)
{
ncases= list.elements;
if (first_expr_arg)
@@ -2921,7 +2794,6 @@ Item_func_case::Item_func_case(THD *thd, List<Item> &list,
list.push_back(else_expr_arg, thd->mem_root);
}
set_arguments(thd, list);
- bzero(&cmp_items, sizeof(cmp_items));
}
/**
@@ -2947,8 +2819,6 @@ Item_func_case::Item_func_case(THD *thd, List<Item> &list,
Item *Item_func_case::find_item(String *str)
{
- uint value_added_map= 0;
-
if (first_expr_num == -1)
{
for (uint i=0 ; i < ncases ; i+=2)
@@ -2962,23 +2832,9 @@ Item *Item_func_case::find_item(String *str)
else
{
/* Compare every WHEN argument with it and return the first match */
- for (uint i=0 ; i < ncases ; i+=2)
- {
- if (args[i]->real_item()->type() == NULL_ITEM)
- continue;
- cmp_type= item_cmp_type(left_cmp_type, args[i]);
- DBUG_ASSERT(cmp_type != ROW_RESULT);
- DBUG_ASSERT(cmp_items[(uint)cmp_type]);
- if (!(value_added_map & (1U << (uint)cmp_type)))
- {
- cmp_items[(uint)cmp_type]->store_value(args[first_expr_num]);
- if ((null_value=args[first_expr_num]->null_value))
- return else_expr_num != -1 ? args[else_expr_num] : 0;
- value_added_map|= 1U << (uint)cmp_type;
- }
- if (cmp_items[(uint)cmp_type]->cmp(args[i]) == FALSE)
- return args[i + 1];
- }
+ uint idx;
+ if (!Predicant_to_list_comparator::cmp(this, &idx, NULL))
+ return args[idx + 1];
}
// No, WHEN clauses all missed, return ELSE expression
return else_expr_num != -1 ? args[else_expr_num] : 0;
@@ -3116,6 +2972,25 @@ static void change_item_tree_if_needed(THD *thd,
}
+bool Item_func_case::prepare_predicant_and_values(THD *thd, uint *found_types)
+{
+ bool have_null= false;
+ uint type_cnt;
+ Type_handler_hybrid_field_type tmp;
+ add_predicant(this, (uint) first_expr_num);
+ for (uint i= 0 ; i < ncases / 2; i++)
+ {
+ if (add_value_skip_null("case..when", this, i * 2, &have_null))
+ return true;
+ }
+ all_values_added(&tmp, &type_cnt, &m_found_types);
+#ifndef DBUG_OFF
+ Predicant_to_list_comparator::debug_print(thd);
+#endif
+ return false;
+}
+
+
void Item_func_case::fix_length_and_dec()
{
Item **agg= arg_buffer;
@@ -3136,37 +3011,41 @@ void Item_func_case::fix_length_and_dec()
if (else_expr_num != -1)
agg[nagg++]= args[else_expr_num];
-
- set_handler_by_field_type(agg_field_type(agg, nagg, true));
- if (Item_func_case::result_type() == STRING_RESULT)
- {
- if (count_string_result_length(Item_func_case::field_type(), agg, nagg))
- return;
- /*
- Copy all THEN and ELSE items back to args[] array.
- Some of the items might have been changed to Item_func_conv_charset.
- */
- for (nagg= 0 ; nagg < ncases / 2 ; nagg++)
- change_item_tree_if_needed(thd, &args[nagg * 2 + 1], agg[nagg]);
+ if (aggregate_for_result(func_name(), agg, nagg, true))
+ return;
+
+ if (fix_attributes(agg, nagg))
+ return;
+
+ /*
+ Copy all modified THEN and ELSE items back to args[] array.
+ Some of the items might have been changed to Item_func_conv_charset.
+ */
+ for (nagg= 0 ; nagg < ncases / 2 ; nagg++)
+ change_item_tree_if_needed(thd, &args[nagg * 2 + 1], agg[nagg]);
+
+ if (else_expr_num != -1)
+ change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
- if (else_expr_num != -1)
- change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
- }
- else
- {
- fix_attributes(agg, nagg);
- }
-
/*
Aggregate first expression and all WHEN expression types
and collations when string comparison
*/
if (first_expr_num != -1)
{
- uint i;
+ if (prepare_predicant_and_values(thd, &m_found_types))
+ {
+ /*
+ If Predicant_to_list_comparator() fails to prepare components,
+ it must put an error into the diagnostics area. This is needed
+ to make fix_fields() catches such errors.
+ */
+ DBUG_ASSERT(thd->is_error());
+ return;
+ }
+
agg[0]= args[first_expr_num];
- left_cmp_type= agg[0]->cmp_type();
/*
As the first expression and WHEN expressions
@@ -3180,10 +3059,6 @@ void Item_func_case::fix_length_and_dec()
if (!(m_found_types= collect_cmp_types(agg, nagg)))
return;
- Item *date_arg= 0;
- if (m_found_types & (1U << TIME_RESULT))
- date_arg= find_date_time_item(args, arg_count, 0);
-
if (m_found_types & (1U << STRING_RESULT))
{
/*
@@ -3221,26 +3096,18 @@ void Item_func_case::fix_length_and_dec()
for (nagg= 0; nagg < ncases / 2; nagg++)
change_item_tree_if_needed(thd, &args[nagg * 2], agg[nagg + 1]);
- }
- for (i= 0; i <= (uint)TIME_RESULT; i++)
- {
- if (m_found_types & (1U << i) && !cmp_items[i])
- {
- DBUG_ASSERT((Item_result)i != ROW_RESULT);
-
- if (!(cmp_items[i]=
- cmp_item::get_comparator((Item_result)i, date_arg,
- cmp_collation.collation)))
- return;
- }
}
+
+ if (make_unique_cmp_items(thd, cmp_collation.collation))
+ return;
}
}
Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
+ const Type_handler *first_expr_cmp_handler;
if (first_expr_num == -1)
{
// None of the arguments are in a comparison context
@@ -3248,6 +3115,7 @@ Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_
return this;
}
+ first_expr_cmp_handler= args[first_expr_num]->type_handler_for_comparison();
for (uint i= 0; i < arg_count; i++)
{
/*
@@ -3286,11 +3154,11 @@ Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_
WHEN 'str2' THEN TRUE
ELSE FALSE END;
*/
- if (m_found_types == (1UL << left_cmp_type))
+ if (m_found_types == (1UL << first_expr_cmp_handler->cmp_type()))
new_item= args[i]->propagate_equal_fields(thd,
Context(
ANY_SUBST,
- left_cmp_type,
+ first_expr_cmp_handler,
cmp_collation.collation),
cond);
}
@@ -3303,13 +3171,14 @@ Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_
replaced to zero-filled constants (only IDENTITY_SUBST allows this).
Such a change for WHEN arguments would require rebuilding cmp_items.
*/
- Item_result tmp_cmp_type= item_cmp_type(args[first_expr_num], args[i]);
- new_item= args[i]->propagate_equal_fields(thd,
- Context(
- ANY_SUBST,
- tmp_cmp_type,
- cmp_collation.collation),
- cond);
+ Type_handler_hybrid_field_type tmp(first_expr_cmp_handler);
+ if (!tmp.aggregate_for_comparison(args[i]->type_handler_for_comparison()))
+ new_item= args[i]->propagate_equal_fields(thd,
+ Context(
+ ANY_SUBST,
+ tmp.type_handler(),
+ cmp_collation.collation),
+ cond);
}
else // THEN and ELSE arguments (they are not in comparison)
{
@@ -3322,18 +3191,6 @@ Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_
}
-uint Item_func_case::decimal_precision() const
-{
- int max_int_part=0;
- for (uint i=0 ; i < ncases ; i+=2)
- set_if_bigger(max_int_part, args[i+1]->decimal_int_part());
-
- if (else_expr_num != -1)
- set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part());
- return MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
-}
-
-
/**
@todo
Fix this so that it prints the whole CASE expression
@@ -3365,20 +3222,6 @@ void Item_func_case::print(String *str, enum_query_type query_type)
}
-void Item_func_case::cleanup()
-{
- uint i;
- DBUG_ENTER("Item_func_case::cleanup");
- Item_func::cleanup();
- for (i= 0; i <= (uint)TIME_RESULT; i++)
- {
- delete cmp_items[i];
- cmp_items[i]= 0;
- }
- DBUG_VOID_RETURN;
-}
-
-
/**
Coalesce - return first not NULL argument.
*/
@@ -3453,33 +3296,6 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
}
-void Item_hybrid_func::fix_attributes(Item **items, uint nitems)
-{
- switch (Item_hybrid_func::result_type()) {
- case STRING_RESULT:
- if (count_string_result_length(Item_hybrid_func::field_type(),
- items, nitems))
- return;
- break;
- case DECIMAL_RESULT:
- collation.set_numeric();
- count_decimal_length(items, nitems);
- break;
- case REAL_RESULT:
- collation.set_numeric();
- count_real_length(items, nitems);
- break;
- case INT_RESULT:
- collation.set_numeric();
- count_only_length(items, nitems);
- decimals= 0;
- break;
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- }
-}
-
/****************************************************************************
Classes and function for the IN operator
****************************************************************************/
@@ -3746,16 +3562,22 @@ void in_datetime::set(uint pos,Item *item)
{
struct packed_longlong *buff= &((packed_longlong*) base)[pos];
- buff->val= item->val_temporal_packed(warn_item);
+ buff->val= item->val_datetime_packed();
buff->unsigned_flag= 1L;
}
-uchar *in_datetime::get_value(Item *item)
+void in_time::set(uint pos,Item *item)
+{
+ struct packed_longlong *buff= &((packed_longlong*) base)[pos];
+
+ buff->val= item->val_time_packed();
+ buff->unsigned_flag= 1L;
+}
+
+uchar *in_temporal::get_value_internal(Item *item, enum_field_types f_type)
{
bool is_null;
Item **tmp_item= lval_cache ? &lval_cache : &item;
- enum_field_types f_type=
- tmp_item[0]->field_type_for_temporal_comparison(warn_item);
tmp.val= get_datetime_value(0, &tmp_item, &lval_cache, f_type, &is_null);
if (item->null_value)
return 0;
@@ -3763,7 +3585,7 @@ uchar *in_datetime::get_value(Item *item)
return (uchar*) &tmp;
}
-Item *in_datetime::create_item(THD *thd)
+Item *in_temporal::create_item(THD *thd)
{
return new (thd->mem_root) Item_datetime(thd);
}
@@ -3824,25 +3646,95 @@ Item *in_decimal::create_item(THD *thd)
}
-cmp_item* cmp_item::get_comparator(Item_result type, Item *warn_item,
- CHARSET_INFO *cs)
+bool Predicant_to_list_comparator::alloc_comparators(THD *thd, uint nargs)
{
- switch (type) {
- case STRING_RESULT:
- return new cmp_item_sort_string(cs);
- case INT_RESULT:
- return new cmp_item_int;
- case REAL_RESULT:
- return new cmp_item_real;
- case ROW_RESULT:
- return new cmp_item_row;
- case DECIMAL_RESULT:
- return new cmp_item_decimal;
- case TIME_RESULT:
- DBUG_ASSERT(warn_item);
- return new cmp_item_datetime(warn_item);
+ size_t nbytes= sizeof(Predicant_to_value_comparator) * nargs;
+ if (!(m_comparators= (Predicant_to_value_comparator *) thd->alloc(nbytes)))
+ return true;
+ memset(m_comparators, 0, nbytes);
+ return false;
+}
+
+
+bool Predicant_to_list_comparator::add_value(const char *funcname,
+ Item_args *args,
+ uint value_index)
+{
+ DBUG_ASSERT(m_predicant_index < args->argument_count());
+ DBUG_ASSERT(value_index < args->argument_count());
+ Type_handler_hybrid_field_type tmp;
+ Item *tmpargs[2];
+ tmpargs[0]= args->arguments()[m_predicant_index];
+ tmpargs[1]= args->arguments()[value_index];
+ if (tmp.aggregate_for_comparison(funcname, tmpargs, 2, true))
+ {
+ DBUG_ASSERT(current_thd->is_error());
+ return true;
+ }
+ m_comparators[m_comparator_count].m_handler= tmp.type_handler();
+ m_comparators[m_comparator_count].m_arg_index= value_index;
+ m_comparator_count++;
+ return false;
+}
+
+
+bool Predicant_to_list_comparator::add_value_skip_null(const char *funcname,
+ Item_args *args,
+ uint value_index,
+ bool *nulls_found)
+{
+ /*
+ Skip explicit NULL constant items.
+ Using real_item() to correctly detect references to explicit NULLs
+ in HAVING clause, e.g. in this example "b" is skipped:
+ SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A');
+ */
+ if (args->arguments()[value_index]->real_item()->type() == Item::NULL_ITEM)
+ {
+ *nulls_found= true;
+ return false;
}
- return 0; // to satisfy compiler :)
+ return add_value(funcname, args, value_index);
+}
+
+
+void Predicant_to_list_comparator::
+ detect_unique_handlers(Type_handler_hybrid_field_type *compatible,
+ uint *unique_count,
+ uint *found_types)
+{
+ *unique_count= 0;
+ *found_types= 0;
+ for (uint i= 0; i < m_comparator_count; i++)
+ {
+ uint idx;
+ if (find_handler(&idx, m_comparators[i].m_handler, i))
+ {
+ m_comparators[i].m_handler_index= i; // New unique handler
+ (*unique_count)++;
+ (*found_types)|= 1U << m_comparators[i].m_handler->cmp_type();
+ compatible->set_handler(m_comparators[i].m_handler);
+ }
+ else
+ {
+ m_comparators[i].m_handler_index= idx; // Non-unique handler
+ }
+ }
+}
+
+
+bool Predicant_to_list_comparator::make_unique_cmp_items(THD *thd,
+ CHARSET_INFO *cs)
+{
+ for (uint i= 0; i < m_comparator_count; i++)
+ {
+ if (m_comparators[i].m_handler && // Skip implicit NULLs
+ m_comparators[i].m_handler_index == i && // Skip non-unuque
+ !(m_comparators[i].m_cmp_item=
+ m_comparators[i].m_handler->make_cmp_item(thd, cs)))
+ return true;
+ }
+ return false;
}
@@ -3883,19 +3775,23 @@ cmp_item_row::~cmp_item_row()
}
-void cmp_item_row::alloc_comparators()
+bool cmp_item_row::alloc_comparators(THD *thd, uint cols)
{
- if (!comparators)
- comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n);
+ if (comparators)
+ {
+ DBUG_ASSERT(cols == n);
+ return false;
+ }
+ return
+ !(comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *) * (n= cols)));
}
void cmp_item_row::store_value(Item *item)
{
DBUG_ENTER("cmp_item_row::store_value");
- n= item->cols();
- alloc_comparators();
- if (comparators)
+ THD *thd= current_thd;
+ if (!alloc_comparators(thd, item->cols()))
{
item->bring_value();
item->null_value= 0;
@@ -3903,10 +3799,25 @@ void cmp_item_row::store_value(Item *item)
{
if (!comparators[i])
{
- DBUG_ASSERT(item->element_index(i)->cmp_type() != TIME_RESULT);
+ /**
+ Comparators for the row elements that have temporal data types
+ are installed at initialization time by prepare_comparators().
+ Here we install comparators for the other data types.
+ There is a bug in the below code. See MDEV-11511.
+ When performing:
+ (predicant0,predicant1) IN ((value00,value01),(value10,value11))
+ It uses only the data type and the collation of the predicant
+ elements only. It should be fixed to aggregate the data type and
+ the collation for all elements at the N-th positions of the
+ predicate and all values:
+ - predicate0, value00, value01
+ - predicate1, value10, value11
+ */
+ Item *elem= item->element_index(i);
+ const Type_handler *handler= elem->type_handler();
+ DBUG_ASSERT(elem->cmp_type() != TIME_RESULT);
if (!(comparators[i]=
- cmp_item::get_comparator(item->element_index(i)->result_type(), 0,
- item->element_index(i)->collation.collation)))
+ handler->make_cmp_item(thd, elem->collation.collation)))
break; // new failed
}
comparators[i]->store_value(item->element_index(i));
@@ -4015,12 +3926,11 @@ cmp_item* cmp_item_decimal::make_same()
}
-void cmp_item_datetime::store_value(Item *item)
+void cmp_item_temporal::store_value_internal(Item *item,
+ enum_field_types f_type)
{
bool is_null;
Item **tmp_item= lval_cache ? &lval_cache : &item;
- enum_field_types f_type=
- tmp_item[0]->field_type_for_temporal_comparison(warn_item);
value= get_datetime_value(0, &tmp_item, &lval_cache, f_type, &is_null);
m_null_value= item->null_value;
}
@@ -4028,21 +3938,34 @@ void cmp_item_datetime::store_value(Item *item)
int cmp_item_datetime::cmp(Item *arg)
{
- const bool rc= value != arg->val_temporal_packed(warn_item);
+ const bool rc= value != arg->val_datetime_packed();
return (m_null_value || arg->null_value) ? UNKNOWN : rc;
}
-int cmp_item_datetime::compare(cmp_item *ci)
+int cmp_item_time::cmp(Item *arg)
{
- cmp_item_datetime *l_cmp= (cmp_item_datetime *)ci;
+ const bool rc= value != arg->val_time_packed();
+ return (m_null_value || arg->null_value) ? UNKNOWN : rc;
+}
+
+
+int cmp_item_temporal::compare(cmp_item *ci)
+{
+ cmp_item_temporal *l_cmp= (cmp_item_temporal *)ci;
return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1);
}
cmp_item *cmp_item_datetime::make_same()
{
- return new cmp_item_datetime(warn_item);
+ return new cmp_item_datetime();
+}
+
+
+cmp_item *cmp_item_time::make_same()
+{
+ return new cmp_item_time();
}
@@ -4133,207 +4056,207 @@ void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref)
eval_not_null_tables(NULL);
}
-static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
+
+bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types)
{
- return cs->coll->strnncollsp(cs,
- (uchar *) x->ptr(),x->length(),
- (uchar *) y->ptr(),y->length());
+ uint type_cnt;
+ have_null= false;
+
+ add_predicant(this, 0);
+ for (uint i= 1 ; i < arg_count; i++)
+ {
+ if (add_value_skip_null(Item_func_in::func_name(), this, i, &have_null))
+ return true;
+ }
+ all_values_added(&m_comparator, &type_cnt, found_types);
+ arg_types_compatible= type_cnt < 2;
+
+#ifndef DBUG_OFF
+ Predicant_to_list_comparator::debug_print(thd);
+#endif
+ return false;
}
+
void Item_func_in::fix_length_and_dec()
{
- Item **arg, **arg_end;
- bool const_itm= 1;
THD *thd= current_thd;
- /* TRUE <=> arguments values will be compared as DATETIMEs. */
- Item *date_arg= 0;
- uint found_types= 0;
- uint type_cnt= 0, i;
- m_compare_type= STRING_RESULT;
- left_cmp_type= args[0]->cmp_type();
- if (!(found_types= collect_cmp_types(args, arg_count, true)))
- return;
-
- for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++)
- {
- if (!arg[0]->const_item())
- {
- const_itm= 0;
- break;
- }
- }
- for (i= 0; i <= (uint)TIME_RESULT; i++)
+ uint found_types;
+ m_comparator.set_handler(type_handler_varchar.type_handler_for_comparison());
+ max_length= 1;
+
+ if (prepare_predicant_and_values(thd, &found_types))
{
- if (found_types & (1U << i))
- {
- (type_cnt)++;
- m_compare_type= (Item_result) i;
- }
+ DBUG_ASSERT(thd->is_error()); // Must set error
+ return;
}
- /*
- First conditions for bisection to be possible:
- 1. All types are similar, and
- 2. All expressions in <in value list> are const
- */
- bool bisection_possible=
- type_cnt == 1 && // 1
- const_itm; // 2
- if (bisection_possible)
+ if (arg_types_compatible) // Bisection condition #1
{
- /*
- In the presence of NULLs, the correct result of evaluating this item
- must be UNKNOWN or FALSE. To achieve that:
- - If type is scalar, we can use bisection and the "have_null" boolean.
- - If type is ROW, we will need to scan all of <in value list> when
- searching, so bisection is impossible. Unless:
- 3. UNKNOWN and FALSE are equivalent results
- 4. Neither left expression nor <in value list> contain any NULL value
- */
-
- if (m_compare_type == ROW_RESULT &&
- ((!is_top_level_item() || negated) && // 3
- (list_contains_null() || args[0]->maybe_null))) // 4
- bisection_possible= false;
+ m_comparator.type_handler()->
+ Item_func_in_fix_comparator_compatible_types(thd, this);
}
-
- if (type_cnt == 1)
+ else
{
- if (m_compare_type == STRING_RESULT &&
- agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
- return;
- arg_types_compatible= TRUE;
+ DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
+ fix_for_scalar_comparison_using_cmp_items(thd, found_types);
+ }
- if (m_compare_type == ROW_RESULT)
- {
- uint cols= args[0]->cols();
- cmp_item_row *cmp= 0;
+ DBUG_EXECUTE_IF("Item_func_in",
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR, "DBUG: types_compatible=%s bisect=%s",
+ arg_types_compatible ? "yes" : "no",
+ array != NULL ? "yes" : "no"););
+}
- if (bisection_possible)
- {
- array= new (thd->mem_root) in_row(thd, arg_count-1, 0);
- cmp= &((in_row*)array)->tmp;
- }
- else
- {
- if (!(cmp= new (thd->mem_root) cmp_item_row))
- return;
- cmp_items[ROW_RESULT]= cmp;
- }
- cmp->n= cols;
- cmp->alloc_comparators();
- for (uint col= 0; col < cols; col++)
- {
- date_arg= find_date_time_item(args, arg_count, col);
- if (date_arg)
- {
- cmp_item **cmp= 0;
- if (array)
- cmp= ((in_row*)array)->tmp.comparators + col;
- else
- cmp= ((cmp_item_row*)cmp_items[ROW_RESULT])->comparators + col;
- *cmp= new (thd->mem_root) cmp_item_datetime(date_arg);
- }
- }
- }
- }
+/**
+ Populate Item_func_in::array with constant not-NULL arguments and sort them.
- if (bisection_possible)
+ Sets "have_null" to true if some of the values appeared to be NULL.
+ Note, explicit NULLs were found during prepare_predicant_and_values().
+ So "have_null" can already be true before the fix_in_vector() call.
+ Here we additionally catch implicit NULLs.
+*/
+void Item_func_in::fix_in_vector()
+{
+ DBUG_ASSERT(array);
+ uint j=0;
+ for (uint i=1 ; i < arg_count ; i++)
{
- /*
- IN must compare INT columns and constants as int values (the same
- way as equality does).
- So we must check here if the column on the left and all the constant
- values on the right can be compared as integers and adjust the
- comparison type accordingly.
-
- See the comment about the similar block in Item_bool_func2
- */
- if (args[0]->real_item()->type() == FIELD_ITEM &&
- !thd->lex->is_view_context_analysis() && m_compare_type != INT_RESULT)
+ array->set(j,args[i]);
+ if (!args[i]->null_value)
+ j++; // include this cell in the array.
+ else
{
- Item_field *field_item= (Item_field*) (args[0]->real_item());
- if (field_item->field_type() == MYSQL_TYPE_LONGLONG ||
- field_item->field_type() == MYSQL_TYPE_YEAR)
- {
- bool all_converted= TRUE;
- for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
- {
- if (!convert_const_to_int(thd, field_item, &arg[0]))
- all_converted= FALSE;
- }
- if (all_converted)
- m_compare_type= INT_RESULT;
- }
- }
- switch (m_compare_type) {
- case STRING_RESULT:
- array=new (thd->mem_root) in_string(thd, arg_count - 1,
- (qsort2_cmp) srtcmp_in,
- cmp_collation.collation);
- break;
- case INT_RESULT:
- array= new (thd->mem_root) in_longlong(thd, arg_count - 1);
- break;
- case REAL_RESULT:
- array= new (thd->mem_root) in_double(thd, arg_count - 1);
- break;
- case ROW_RESULT:
/*
- The row comparator was created at the beginning but only DATETIME
- items comparators were initialized. Call store_value() to setup
- others.
+ We don't put NULL values in array, to avoid erronous matches in
+ bisection.
*/
- ((in_row*)array)->tmp.store_value(args[0]);
- break;
- case DECIMAL_RESULT:
- array= new (thd->mem_root) in_decimal(thd, arg_count - 1);
- break;
- case TIME_RESULT:
- date_arg= find_date_time_item(args, arg_count, 0);
- array= new (thd->mem_root) in_datetime(thd, date_arg, arg_count - 1);
- break;
+ have_null= 1;
}
- if (!array || thd->is_fatal_error) // OOM
- return;
- uint j=0;
- for (uint i=1 ; i < arg_count ; i++)
+ }
+ if ((array->used_count= j))
+ array->sort();
+}
+
+
+/**
+ Convert all items in <in value list> to INT.
+
+ IN must compare INT columns and constants as int values (the same
+ way as equality does).
+ So we must check here if the column on the left and all the constant
+ values on the right can be compared as integers and adjust the
+ comparison type accordingly.
+
+ See the comment about the similar block in Item_bool_func2
+*/
+bool Item_func_in::value_list_convert_const_to_int(THD *thd)
+{
+ if (args[0]->real_item()->type() == FIELD_ITEM &&
+ !thd->lex->is_view_context_analysis())
+ {
+ Item_field *field_item= (Item_field*) (args[0]->real_item());
+ if (field_item->field_type() == MYSQL_TYPE_LONGLONG ||
+ field_item->field_type() == MYSQL_TYPE_YEAR)
{
- array->set(j,args[i]);
- if (!args[i]->null_value)
- j++; // include this cell in the array.
- else
+ bool all_converted= TRUE;
+ Item **arg, **arg_end;
+ for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
{
- /*
- We don't put NULL values in array, to avoid erronous matches in
- bisection.
- */
- have_null= 1;
+ if (!convert_const_to_int(thd, field_item, &arg[0]))
+ all_converted= FALSE;
}
+ if (all_converted)
+ m_comparator.set_handler(&type_handler_longlong);
}
- if ((array->used_count= j))
- array->sort();
}
- else
+ return thd->is_fatal_error; // Catch errrors in convert_const_to_int
+}
+
+
+/**
+ Historically this code installs comparators at initialization time
+ for temporal ROW elements only. All other comparators are installed later,
+ during the first store_value(). This causes the bug MDEV-11511.
+ See also comments in cmp_item_row::store_value().
+*/
+bool cmp_item_row::prepare_comparators(THD *thd, Item **args, uint arg_count)
+{
+ for (uint col= 0; col < n; col++)
{
- if (found_types & (1U << TIME_RESULT))
- date_arg= find_date_time_item(args, arg_count, 0);
- if (found_types & (1U << STRING_RESULT) &&
- agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
- return;
- for (i= 0; i <= (uint) TIME_RESULT; i++)
+ Item *date_arg= find_date_time_item(args, arg_count, col);
+ if (date_arg)
{
- if (found_types & (1U << i) && !cmp_items[i])
- {
- if (!cmp_items[i] && !(cmp_items[i]=
- cmp_item::get_comparator((Item_result)i, date_arg,
- cmp_collation.collation)))
- return;
- }
+ // TODO: do like the scalar comparators do
+ const Type_handler *h= date_arg->type_handler();
+ comparators[col]= h->field_type() == MYSQL_TYPE_TIME ?
+ (cmp_item *) new (thd->mem_root) cmp_item_time() :
+ (cmp_item *) new (thd->mem_root) cmp_item_datetime();
+ if (!comparators[col])
+ return true;
}
}
- max_length= 1;
+ return false;
+}
+
+
+bool Item_func_in::fix_for_row_comparison_using_bisection(THD *thd)
+{
+ uint cols= args[0]->cols();
+ if (!(array= new (thd->mem_root) in_row(thd, arg_count-1, 0)))
+ return true;
+ cmp_item_row *cmp= &((in_row*)array)->tmp;
+ if (cmp->alloc_comparators(thd, cols) ||
+ cmp->prepare_comparators(thd, args, arg_count))
+ return true;
+ /*
+ Only DATETIME items comparators were initialized.
+ Call store_value() to setup others.
+ */
+ cmp->store_value(args[0]);
+ if (thd->is_fatal_error) // OOM
+ return true;
+ fix_in_vector();
+ return false;
+}
+
+
+/**
+ This method is called for scalar data types when bisection is not possible,
+ for example:
+ - Some of args[1..arg_count] are not constants.
+ - args[1..arg_count] are constants, but pairs {args[0],args[1..arg_count]}
+ are compared by different data types, e.g.:
+ WHERE decimal_expr IN (1, 1e0)
+ The pair {args[0],args[1]} is compared by type_handler_decimal.
+ The pair {args[0],args[2]} is compared by type_handler_double.
+*/
+bool Item_func_in::fix_for_scalar_comparison_using_cmp_items(THD *thd,
+ uint found_types)
+{
+ if (found_types & (1U << STRING_RESULT) &&
+ agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
+ return true;
+ if (make_unique_cmp_items(thd, cmp_collation.collation))
+ return true;
+ return false;
+}
+
+
+/**
+ This method is called for the ROW data type when bisection is not possible.
+*/
+bool Item_func_in::fix_for_row_comparison_using_cmp_items(THD *thd)
+{
+ if (make_unique_cmp_items(thd, cmp_collation.collation))
+ return true;
+ DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row);
+ DBUG_ASSERT(get_comparator_cmp_item(0));
+ cmp_item_row *cmp_row= (cmp_item_row*) get_comparator_cmp_item(0);
+ return cmp_row->alloc_comparators(thd, args[0]->cols()) ||
+ cmp_row->prepare_comparators(thd, args, arg_count);
}
@@ -4375,9 +4298,7 @@ void Item_func_in::print(String *str, enum_query_type query_type)
longlong Item_func_in::val_int()
{
- cmp_item *in_item;
DBUG_ASSERT(fixed == 1);
- uint value_added_map= 0;
if (array)
{
bool tmp=array->find(args[0]);
@@ -4395,29 +4316,13 @@ longlong Item_func_in::val_int()
if ((null_value= args[0]->real_item()->type() == NULL_ITEM))
return 0;
- have_null= 0;
- for (uint i= 1 ; i < arg_count ; i++)
+ null_value= have_null;
+ uint idx;
+ if (!Predicant_to_list_comparator::cmp(this, &idx, &null_value))
{
- if (args[i]->real_item()->type() == NULL_ITEM)
- {
- have_null= TRUE;
- continue;
- }
- Item_result cmp_type= item_cmp_type(left_cmp_type, args[i]);
- in_item= cmp_items[(uint)cmp_type];
- DBUG_ASSERT(in_item);
- if (!(value_added_map & (1U << (uint)cmp_type)))
- {
- in_item->store_value(args[0]);
- value_added_map|= 1U << (uint)cmp_type;
- }
- const int rc= in_item->cmp(args[i]);
- if (rc == FALSE)
- return (longlong) (!negated);
- have_null|= (rc == UNKNOWN);
+ null_value= false;
+ return (longlong) (!negated);
}
-
- null_value= have_null;
return (longlong) (!null_value && negated);
}
@@ -5662,6 +5567,7 @@ Item_func_regexp_instr::fix_length_and_dec()
re.init(cmp_collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
+ max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate
}
@@ -6141,10 +6047,11 @@ Item *Item_bool_rowready_func2::negated_item(THD *thd)
of the type Item_field or Item_direct_view_ref(Item_field).
*/
-Item_equal::Item_equal(THD *thd, Item *f1, Item *f2, bool with_const_item):
+Item_equal::Item_equal(THD *thd, const Type_handler *handler,
+ Item *f1, Item *f2, bool with_const_item):
Item_bool_func(thd), eval_item(0), cond_false(0), cond_true(0),
context_field(NULL), link_equal_fields(FALSE),
- m_compare_type(item_cmp_type(f1, f2)),
+ m_compare_handler(handler),
m_compare_collation(f2->collation.collation)
{
const_item_cache= 0;
@@ -6170,7 +6077,7 @@ Item_equal::Item_equal(THD *thd, Item *f1, Item *f2, bool with_const_item):
Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
Item_bool_func(thd), eval_item(0), cond_false(0), cond_true(0),
context_field(NULL), link_equal_fields(FALSE),
- m_compare_type(item_equal->m_compare_type),
+ m_compare_handler(item_equal->m_compare_handler),
m_compare_collation(item_equal->m_compare_collation)
{
const_item_cache= 0;
@@ -6213,7 +6120,7 @@ void Item_equal::add_const(THD *thd, Item *c)
return;
}
Item *const_item= get_const();
- switch (Item_equal::compare_type()) {
+ switch (Item_equal::compare_type_handler()->cmp_type()) {
case TIME_RESULT:
{
enum_field_types f_type= context_field->field_type();
@@ -6692,8 +6599,8 @@ longlong Item_equal::val_int()
void 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);
+ const Type_handler *handler= item->type_handler();
+ eval_item= handler->make_cmp_item(current_thd, item->collation.collation);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 8ff789d983a..604ca5b8c81 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -47,7 +47,7 @@ typedef int (*Item_field_cmpfunc)(Item *f1, Item *f2, void *arg);
class Arg_comparator: public Sql_alloc
{
Item **a, **b;
- Item_result m_compare_type;
+ const Type_handler *m_compare_handler;
CHARSET_INFO *m_compare_collation;
arg_cmp_func func;
Item_func_or_sum *owner;
@@ -57,7 +57,7 @@ class Arg_comparator: public Sql_alloc
/* Fields used in DATE/DATETIME comparison. */
Item *a_cache, *b_cache; // Cached values of a and b items
// when one of arguments is NULL.
- int set_compare_func(Item_func_or_sum *owner, Item_result type);
+
int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2);
int compare_temporal(enum_field_types type);
@@ -67,17 +67,27 @@ public:
/* Allow owner function to use string buffers. */
String value1, value2;
- Arg_comparator(): m_compare_type(STRING_RESULT),
+ Arg_comparator():
+ m_compare_handler(&type_handler_null),
m_compare_collation(&my_charset_bin),
set_null(TRUE), comparators(0),
a_cache(0), b_cache(0) {};
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2),
- m_compare_type(STRING_RESULT),
+ m_compare_handler(&type_handler_null),
m_compare_collation(&my_charset_bin),
set_null(TRUE), comparators(0),
a_cache(0), b_cache(0) {};
public:
+ bool set_cmp_func_for_row_arguments();
+ bool set_cmp_func_row();
+ bool set_cmp_func_string();
+ bool set_cmp_func_time();
+ bool set_cmp_func_datetime();
+ bool set_cmp_func_int();
+ bool set_cmp_func_real();
+ bool set_cmp_func_decimal();
+
inline int set_cmp_func(Item_func_or_sum *owner_arg,
Item **a1, Item **a2, bool set_null_arg)
{
@@ -108,14 +118,14 @@ public:
int compare_e_time() { return compare_e_temporal(MYSQL_TYPE_TIME); }
Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
- Item_result type);
- static arg_cmp_func comparator_matrix [6][2];
+ const Type_handler *type);
inline bool is_owner_equal_func()
{
return (owner->type() == Item::FUNC_ITEM &&
((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC);
}
- Item_result compare_type() const { return m_compare_type; }
+ const Type_handler *compare_type_handler() const { return m_compare_handler; }
+ Item_result compare_type() const { return m_compare_handler->cmp_type(); }
CHARSET_INFO *compare_collation() const { return m_compare_collation; }
Arg_comparator *subcomparators() const { return comparators; }
void cleanup()
@@ -194,6 +204,7 @@ public:
Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_long; }
bool is_bool_type() { return true; }
virtual CHARSET_INFO *compare_collation() const { return NULL; }
void fix_length_and_dec() { decimals=0; max_length=1; }
@@ -382,7 +393,7 @@ public:
Specifies which result type the function uses to compare its arguments.
This method is used in equal field propagation.
*/
- virtual Item_result compare_type() const
+ virtual const Type_handler *compare_type_handler() const
{
/*
Have STRING_RESULT by default, which means the function compares
@@ -390,7 +401,7 @@ public:
and for Item_func_spatial_rel.
Note, Item_bool_rowready_func2 overrides this default behaviour.
*/
- return STRING_RESULT;
+ return &type_handler_varchar;
}
SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
{
@@ -470,12 +481,14 @@ class Item_bool_rowready_func2 :public Item_bool_func2_with_rev
{
protected:
Arg_comparator cmp;
+ bool check_arguments() const
+ {
+ return check_argument_types_like_args0();
+ }
public:
Item_bool_rowready_func2(THD *thd, Item *a, Item *b):
Item_bool_func2_with_rev(thd, a, b), cmp(tmp_arg, tmp_arg + 1)
- {
- allowed_arg_cols= 0; // Fetch this value from first argument
- }
+ { }
void print(String *str, enum_query_type query_type)
{
Item_func::print_op(str, query_type);
@@ -487,7 +500,7 @@ public:
{
Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST,
- cmp.compare_type(),
+ cmp.compare_type_handler(),
compare_collation()),
cond);
return this;
@@ -498,7 +511,10 @@ public:
return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
}
CHARSET_INFO *compare_collation() const { return cmp.compare_collation(); }
- Item_result compare_type() const { return cmp.compare_type(); }
+ const Type_handler *compare_type_handler() const
+ {
+ return cmp.compare_type_handler();
+ }
Arg_comparator *get_comparator() { return &cmp; }
void cleanup()
{
@@ -824,10 +840,10 @@ class Item_func_opt_neg :public Item_bool_func
{
protected:
/*
- The result type that will be used for comparison.
- cmp_type() of all arguments are collected to here.
+ The data type handler that will be used for comparison.
+ Data type handlers of all arguments are mixed to here.
*/
- Item_result m_compare_type;
+ Type_handler_hybrid_field_type m_comparator;
/*
The collation that will be used for comparison in case
when m_compare_type is STRING_RESULT.
@@ -862,15 +878,22 @@ protected:
Field *field, Item *value);
public:
String value0,value1,value2;
- /* TRUE <=> arguments will be compared as dates. */
- Item *compare_as_dates;
Item_func_between(THD *thd, Item *a, Item *b, Item *c):
- Item_func_opt_neg(thd, a, b, c), compare_as_dates(FALSE) { }
- longlong val_int();
+ Item_func_opt_neg(thd, a, b, c) { }
+ longlong val_int()
+ {
+ DBUG_ASSERT(fixed);
+ return m_comparator.type_handler()->Item_func_between_val_int(this);
+ }
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_string(THD *)
+ {
+ return agg_arg_charsets_for_comparison(cmp_collation, args, 3);
+ }
+ bool fix_length_and_dec_numeric(THD *);
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);
@@ -883,23 +906,29 @@ public:
{
Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST,
- m_compare_type,
+ m_comparator.type_handler(),
compare_collation()),
cond);
return this;
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_between>(thd, mem_root, this); }
+
+ longlong val_int_cmp_string();
+ longlong val_int_cmp_temporal();
+ longlong val_int_cmp_int();
+ longlong val_int_cmp_real();
+ longlong val_int_cmp_decimal();
};
-class Item_func_strcmp :public Item_int_func
+class Item_func_strcmp :public Item_long_func
{
String value1, value2;
DTCollation cmp_collation;
public:
Item_func_strcmp(THD *thd, Item *a, Item *b):
- Item_int_func(thd, a, b) {}
+ Item_long_func(thd, a, b) {}
longlong val_int();
uint decimal_precision() const { return 1; }
const char *func_name() const { return "strcmp"; }
@@ -920,17 +949,19 @@ struct interval_range
my_decimal dec;
};
-class Item_func_interval :public Item_int_func
+class Item_func_interval :public Item_long_func
{
Item_row *row;
bool use_decimal_comparison;
interval_range *intervals;
-public:
- Item_func_interval(THD *thd, Item_row *a):
- Item_int_func(thd, a), row(a), intervals(0)
+ bool check_arguments() const
{
- allowed_arg_cols= 0; // Fetch this value from first argument
+ return check_argument_types_like_args0();
}
+public:
+ Item_func_interval(THD *thd, Item_row *a):
+ Item_long_func(thd, a), row(a), intervals(0)
+ { }
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
@@ -945,13 +976,13 @@ public:
};
-class Item_func_coalesce :public Item_func_hybrid_field_type
+class Item_func_coalesce :public Item_func_case_expression
{
public:
Item_func_coalesce(THD *thd, Item *a, Item *b):
- Item_func_hybrid_field_type(thd, a, b) {}
+ Item_func_case_expression(thd, a, b) {}
Item_func_coalesce(THD *thd, List<Item> &list):
- Item_func_hybrid_field_type(thd, list) {}
+ Item_func_case_expression(thd, list) {}
double real_op();
longlong int_op();
String *str_op(String *);
@@ -959,8 +990,8 @@ public:
bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
void fix_length_and_dec()
{
- set_handler_by_field_type(agg_field_type(args, arg_count, true));
- fix_attributes(args, arg_count);
+ if (!aggregate_for_result(func_name(), args, arg_count, true))
+ fix_attributes(args, arg_count);
}
const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; }
@@ -973,21 +1004,49 @@ public:
Case abbreviations that aggregate its result field type by two arguments:
IFNULL(arg1, arg2)
IF(switch, arg1, arg2)
+ NVL2(switch, arg1, arg2)
*/
-class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type
+class Item_func_case_abbreviation2 :public Item_func_case_expression
{
protected:
void fix_length_and_dec2(Item **items)
{
- set_handler_by_field_type(agg_field_type(items, 2, true));
- fix_attributes(items, 2);
+ if (!aggregate_for_result(func_name(), items, 2, true))
+ fix_attributes(items, 2);
}
- uint decimal_precision2(Item **args) const;
+
+ void cache_type_info(const Item *source, bool maybe_null_arg)
+ {
+ Type_std_attributes::set(source);
+ set_handler(source->type_handler());
+ maybe_null= maybe_null_arg;
+ }
+
+ void fix_length_and_dec2_eliminate_null(Item **items)
+ {
+ // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
+ if (items[0]->type() == NULL_ITEM)
+ {
+ cache_type_info(items[1], true);
+ // If both arguments are NULL, make resulting type BINARY(0).
+ if (items[1]->type() == NULL_ITEM)
+ set_handler(&type_handler_string);
+ }
+ else if (items[1]->type() == NULL_ITEM)
+ {
+ cache_type_info(items[0], true);
+ }
+ else
+ {
+ fix_length_and_dec2(items);
+ }
+ }
+
public:
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
- Item_func_hybrid_field_type(thd, a, b) { }
+ Item_func_case_expression(thd, a, b) { }
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c):
- Item_func_hybrid_field_type(thd, a, b, c) { }
+ Item_func_case_expression(thd, a, b, c) { }
};
@@ -1007,35 +1066,67 @@ public:
maybe_null= args[1]->maybe_null;
}
const char *func_name() const { return "ifnull"; }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table, false, false); }
table_map not_null_tables() const { return 0; }
- uint decimal_precision() const
- {
- return Item_func_case_abbreviation2::decimal_precision2(args);
- }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_ifnull>(thd, mem_root, this); }
};
-class Item_func_if :public Item_func_case_abbreviation2
+/**
+ Case abbreviations that have a switch argument and
+ two return arguments to choose from. Returns the value
+ of either of the two return arguments depending on the switch argument value.
+
+ IF(switch, arg1, arg2)
+ NVL(switch, arg1, arg2)
+*/
+class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2
{
+protected:
+ virtual Item *find_item() const= 0;
+
+public:
+ Item_func_case_abbreviation2_switch(THD *thd, Item *a, Item *b, Item *c)
+ :Item_func_case_abbreviation2(thd, a, b, c)
+ { }
+
+ bool date_op(MYSQL_TIME *ltime, uint fuzzydate)
+ {
+ return get_date_with_conversion_from_item(find_item(), ltime, fuzzydate);
+ }
+ longlong int_op()
+ {
+ return val_int_from_item(find_item());
+ }
+ double real_op()
+ {
+ return val_real_from_item(find_item());
+ }
+ my_decimal *decimal_op(my_decimal *decimal_value)
+ {
+ return val_decimal_from_item(find_item(), decimal_value);
+ }
+ String *str_op(String *str)
+ {
+ return val_str_from_item(find_item(), str);
+ }
+};
+
+
+class Item_func_if :public Item_func_case_abbreviation2_switch
+{
+protected:
+ Item *find_item() const { return args[0]->val_bool() ? args[1] : args[2]; }
+
public:
Item_func_if(THD *thd, Item *a, Item *b, Item *c):
- Item_func_case_abbreviation2(thd, a, b, c)
+ Item_func_case_abbreviation2_switch(thd, a, b, c)
{}
- bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
- longlong int_op();
- double real_op();
- my_decimal *decimal_op(my_decimal *);
- String *str_op(String *);
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
- uint decimal_precision() const
+ void fix_length_and_dec()
{
- return Item_func_case_abbreviation2::decimal_precision2(args + 1);
+ fix_length_and_dec2_eliminate_null(args + 1);
}
const char *func_name() const { return "if"; }
bool eval_not_null_tables(void *opt_arg);
@@ -1047,7 +1138,26 @@ private:
};
-class Item_func_nullif :public Item_func_hybrid_field_type
+class Item_func_nvl2 :public Item_func_case_abbreviation2_switch
+{
+protected:
+ Item *find_item() const { return args[0]->is_null() ? args[2] : args[1]; }
+
+public:
+ Item_func_nvl2(THD *thd, Item *a, Item *b, Item *c):
+ Item_func_case_abbreviation2_switch(thd, a, b, c)
+ {}
+ const char *func_name() const { return "nvl2"; }
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec2_eliminate_null(args + 1);
+ }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_nvl2>(thd, mem_root, this); }
+};
+
+
+class Item_func_nullif :public Item_func_case_expression
{
Arg_comparator cmp;
/*
@@ -1085,7 +1195,7 @@ public:
See also Item_func_nullif::fix_length_and_dec().
*/
Item_func_nullif(THD *thd, Item *a, Item *b):
- Item_func_hybrid_field_type(thd, a, b, a),
+ Item_func_case_expression(thd, a, b, a),
m_cache(NULL),
m_arg0(NULL)
{ arg_count--; }
@@ -1101,7 +1211,6 @@ public:
my_decimal *decimal_op(my_decimal *);
void 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"; }
void print(String *str, enum_query_type query_type);
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
@@ -1111,7 +1220,8 @@ public:
bool is_null();
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
- Context cmpctx(ANY_SUBST, cmp.compare_type(), cmp.compare_collation());
+ Context cmpctx(ANY_SUBST, cmp.compare_type_handler(),
+ cmp.compare_collation());
const Item *old0= args[0];
args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
cond, &args[0]);
@@ -1264,18 +1374,16 @@ public:
If the left item is a constant one then its value is cached in the
lval_cache variable.
*/
-class in_datetime :public in_longlong
+class in_temporal :public in_longlong
{
+protected:
+ uchar *get_value_internal(Item *item, enum_field_types f_type);
public:
- /* An item used to issue warnings. */
- Item *warn_item;
/* Cache for the left item. */
Item *lval_cache;
- in_datetime(THD *thd, Item *warn_item_arg, uint elements)
- :in_longlong(thd, elements), warn_item(warn_item_arg), lval_cache(0) {};
- void set(uint pos,Item *item);
- uchar *get_value(Item *item);
+ in_temporal(THD *thd, uint elements)
+ :in_longlong(thd, elements), lval_cache(0) {};
Item *create_item(THD *thd);
void value_to_item(uint pos, Item *item)
{
@@ -1287,6 +1395,30 @@ public:
};
+class in_datetime :public in_temporal
+{
+public:
+ in_datetime(THD *thd, uint elements)
+ :in_temporal(thd, elements)
+ {}
+ void set(uint pos,Item *item);
+ uchar *get_value(Item *item)
+ { return get_value_internal(item, MYSQL_TYPE_DATETIME); }
+};
+
+
+class in_time :public in_temporal
+{
+public:
+ in_time(THD *thd, uint elements)
+ :in_temporal(thd, elements)
+ {}
+ void set(uint pos,Item *item);
+ uchar *get_value(Item *item)
+ { return get_value_internal(item, MYSQL_TYPE_TIME); }
+};
+
+
class in_double :public in_vector
{
double tmp;
@@ -1339,8 +1471,6 @@ public:
virtual int cmp(Item *item)= 0;
// for optimized IN with row
virtual int compare(cmp_item *item)= 0;
- static cmp_item* get_comparator(Item_result type, Item * warn_item,
- CHARSET_INFO *cs);
virtual cmp_item *make_same()= 0;
virtual void store_value_by_template(THD *thd, cmp_item *tmpl, Item *item)
{
@@ -1438,20 +1568,47 @@ public:
If the left item is a constant one then its value is cached in the
lval_cache variable.
*/
-class cmp_item_datetime : public cmp_item_scalar
+class cmp_item_temporal: public cmp_item_scalar
{
+protected:
longlong value;
+ void store_value_internal(Item *item, enum_field_types type);
public:
- /* Item used for issuing warnings. */
- Item *warn_item;
/* Cache for the left item. */
Item *lval_cache;
- cmp_item_datetime(Item *warn_item_arg)
- : warn_item(warn_item_arg), lval_cache(0) {}
- void store_value(Item *item);
- int cmp(Item *arg);
+ cmp_item_temporal()
+ :lval_cache(0) {}
int compare(cmp_item *ci);
+};
+
+
+class cmp_item_datetime: public cmp_item_temporal
+{
+public:
+ cmp_item_datetime()
+ :cmp_item_temporal()
+ { }
+ void store_value(Item *item)
+ {
+ store_value_internal(item, MYSQL_TYPE_DATETIME);
+ }
+ int cmp(Item *arg);
+ cmp_item *make_same();
+};
+
+
+class cmp_item_time: public cmp_item_temporal
+{
+public:
+ cmp_item_time()
+ :cmp_item_temporal()
+ { }
+ void store_value(Item *item)
+ {
+ store_value_internal(item, MYSQL_TYPE_TIME);
+ }
+ int cmp(Item *arg);
cmp_item *make_same();
};
@@ -1526,6 +1683,330 @@ public:
};
+/**
+ A helper class to handle situations when some item "pred" (the predicant)
+ is consequently compared to a list of other items value0..valueN (the values).
+ Currently used to handle:
+ - <in predicate>
+ pred IN (value0, value1, value2)
+ - <simple case>
+ CASE pred WHEN value0 .. WHEN value1 .. WHEN value2 .. END
+
+ Every pair {pred,valueN} can be compared by its own Type_handler.
+ Some pairs can use the same Type_handler.
+ In cases when all pairs use exactly the same Type_handler,
+ we say "all types are compatible".
+
+ For example, for an expression
+ 1 IN (1, 1e0, 1.0, 2)
+ - pred is 1
+ - value0 is 1
+ - value1 is 1e0
+ - value2 is 1.1
+ - value3 is 2
+
+ Pairs (pred,valueN) are compared as follows:
+ N expr1 Type
+ - ----- ----
+ 0 1 INT
+ 1 1e0 DOUBLE
+ 2 1.0 DECIMAL
+ 3 2 INT
+
+ Types are not compatible in this example.
+
+ During add_value() calls, each pair {pred,valueN} is analysed:
+ - If valueN is an explicit NULL, it can be ignored in the caller asks to do so
+ - If valueN is not an explicit NULL (or if the caller didn't ask to skip
+ NULLs), then the value add an element in the array m_comparators[].
+
+ Every element m_comparators[] stores the following information:
+ 1. m_arg_index - the position of the value expression in the original
+ argument array, e.g. in Item_func_in::args[] or Item_func_case::args[].
+
+ 2. m_handler - the pointer to the data type handler that the owner
+ will use to compare the pair {args[m_predicate_index],args[m_arg_index]}.
+
+ 3. m_handler_index - the index of an m_comparators[] element corresponding
+ to the leftmost pair that uses exactly the same Type_handler for
+ comparison. m_handler_index helps to maintain unique data type handlers.
+ - m_comparators[i].m_handler_index==i means that this is the
+ leftmost pair that uses the Type_handler m_handler for comparision.
+ - If m_comparators[i].m_handlex_index!=i, it means that some earlier
+ element m_comparators[j<i] is already using this Type_handler
+ pointed by m_handler.
+
+ 4. m_cmp_item - the pointer to a cmp_item instance to handle comparison
+ for this pair. Only unique type handlers have m_cmp_item!=NULL.
+ Non-unique type handlers share the same cmp_item instance.
+ For all m_comparators[] elements the following assersion it true:
+ (m_handler_index==i) == (m_cmp_item!=NULL)
+*/
+class Predicant_to_list_comparator
+{
+ // Allocate memory on thd memory root for "nvalues" values.
+ bool alloc_comparators(THD *thd, uint nvalues);
+
+ /**
+ Look up m_comparators[] for a comparator using the given data type handler.
+ @param [OUT] idx - the index of the found comparator is returned here
+ @param [IN] handler - the data type handler to find
+ @param [IN] count - search in the range [0,count) only
+ @retval true - this type handler was not found
+ (*idx is not defined in this case).
+ @retval false - this type handler was found (the position of the
+ found handler is returned in idx).
+ */
+ bool find_handler(uint *idx, const Type_handler *handler, uint count)
+ {
+ DBUG_ASSERT(count < m_comparator_count);
+ for (uint i= 0 ; i < count; i++)
+ {
+ if (m_comparators[i].m_handler == handler)
+ {
+ *idx= i;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ Populate m_comparators[i].m_handler_index for all elements in
+ m_comparators using the information in m_comparators[i].m_handlers,
+ which was previously populated by a add_predicant() call and a number
+ of add_value() calls.
+ @param [OUT] compatible - If all comparator types are compatible,
+ their data type handler is returned here.
+ @param [OUT] unuque_cnt - The number of unique data type handlers found.
+ If the value returned in *unique_cnt is 0,
+ it means all values were explicit NULLs:
+ expr0 IN (NULL,NULL,..,NULL)
+ @param [OUT] found_type - The bit mask for all found cmp_type()'s.
+ */
+ void detect_unique_handlers(Type_handler_hybrid_field_type *compatible,
+ uint *unique_cnt, uint *found_types);
+ /**
+ Creates a cmp_item instances for all unique handlers and stores
+ them into m_comparators[i].m_cmp_item, using the information previously
+ populated by add_predicant(), add_value(), detect_unque_handlers().
+ */
+
+ /*
+ Compare the predicant to the value pointed by m_comparators[i].
+ @param args - the same argument array which was previously used
+ with add_predicant() and add_value().
+ @param i - which pair to check.
+ @retval true - the predicant is not equal to the value.
+ @retval false - the predicant is equal to the value.
+ @retval UNKNOWN - the result is uncertain yet because the predicant
+ and/or the value returned NULL,
+ more pairs {pred,valueN} should be checked.
+ */
+ int cmp_arg(Item_args *args, uint i)
+ {
+ Predicant_to_value_comparator *cmp=
+ &m_comparators[m_comparators[i].m_handler_index];
+ cmp_item *in_item= cmp->m_cmp_item;
+ DBUG_ASSERT(in_item);
+ /*
+ If this is the leftmost pair that uses the data type handler
+ pointed by m_comparators[i].m_handler, then we need to cache
+ the predicant value representation used by this handler.
+ */
+ if (m_comparators[i].m_handler_index == i)
+ in_item->store_value(args->arguments()[m_predicant_index]);
+ /*
+ If the predicant item has null_value==true then:
+ - In case of scalar expression we can returns UNKNOWN immediately.
+ No needs to check the result of the value item.
+ - In case of ROW, null_value==true means that *some* row elements
+ returned NULL, but *some* elements can still be non-NULL!
+ We need to get the result of the value item and test
+ if non-NULL elements in the predicant and the value produce
+ TRUE (not equal), or UNKNOWN.
+ */
+ if (args->arguments()[m_predicant_index]->null_value &&
+ m_comparators[i].m_handler != &type_handler_row)
+ return UNKNOWN;
+ return in_item->cmp(args->arguments()[m_comparators[i].m_arg_index]);
+ }
+
+ /**
+ Predicant_to_value_comparator - a comparator for one pair (pred,valueN).
+ See comments above.
+ */
+ struct Predicant_to_value_comparator
+ {
+ const Type_handler *m_handler;
+ cmp_item *m_cmp_item;
+ uint m_arg_index;
+ uint m_handler_index;
+ void cleanup()
+ {
+ if (m_cmp_item)
+ delete m_cmp_item;
+ memset(this, 0, sizeof(*this));
+ }
+ };
+
+ Predicant_to_value_comparator *m_comparators; // The comparator array
+ uint m_comparator_count;// The number of elements in m_comparators[]
+ uint m_predicant_index; // The position of the predicant in its argument list,
+ // e.g. for Item_func_in m_predicant_index is 0,
+ // as predicant is stored in Item_func_in::args[0].
+ // For Item_func_case m_predicant_index is
+ // set to Item_func_case::first_expr_num.
+
+public:
+ Predicant_to_list_comparator(THD *thd, uint nvalues)
+ :m_comparator_count(0),
+ m_predicant_index(0)
+ {
+ alloc_comparators(thd, nvalues);
+ }
+
+ uint comparator_count() const { return m_comparator_count; }
+ const Type_handler *get_comparator_type_handler(uint i) const
+ {
+ DBUG_ASSERT(i < m_comparator_count);
+ return m_comparators[i].m_handler;
+ }
+ uint get_comparator_arg_index(uint i) const
+ {
+ DBUG_ASSERT(i < m_comparator_count);
+ return m_comparators[i].m_arg_index;
+ }
+ cmp_item *get_comparator_cmp_item(uint i) const
+ {
+ DBUG_ASSERT(i < m_comparator_count);
+ return m_comparators[i].m_cmp_item;
+ }
+
+#ifndef DBUG_OFF
+ void debug_print(THD *thd)
+ {
+ for (uint i= 0; i < m_comparator_count; i++)
+ {
+ DBUG_EXECUTE_IF("Predicant_to_list_comparator",
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR, "DBUG: [%d] arg=%d handler=%d (%s)", i,
+ m_comparators[i].m_arg_index,
+ m_comparators[i].m_handler_index,
+ m_comparators[m_comparators[i].m_handler_index].
+ m_handler->name().ptr()););
+ }
+ }
+#endif
+
+ void add_predicant(Item_args *args, uint predicant_index)
+ {
+ DBUG_ASSERT(m_comparator_count == 0); // Set in constructor
+ DBUG_ASSERT(m_predicant_index == 0); // Set in constructor
+ DBUG_ASSERT(predicant_index < args->argument_count());
+ m_predicant_index= predicant_index;
+ }
+ /**
+ Add a new element into m_comparators[], using a {pred,valueN} pair.
+
+ @param funcname - the name of the operation, for error reporting
+ @param args - the owner function's argument list
+ @param value_index - the value position in args
+ @retval true - could not add an element because of non-comparable
+ arguments (e.g. ROWs with size)
+ @retval false - a new element was successfully added.
+ */
+ bool add_value(const char *funcname, Item_args *args, uint value_index);
+
+ /**
+ Add a new element into m_comparators[], ignoring explicit NULL values.
+ If the value appeared to be an explicit NULL, nulls_found[0] is set to true.
+ */
+ bool add_value_skip_null(const char *funcname,
+ Item_args *args, uint value_index,
+ bool *nulls_found);
+
+ /**
+ Signal "this" that there will be no new add_value*() calls,
+ so it can prepare its internal structures for comparison.
+
+ @param [OUT] compatible - If all comparators are compatible,
+ their data type handler is returned here.
+ @param [OUT] unuque_cnt - The number of unique data type handlers found.
+ If the value returned in *unique_cnt is 0,
+ it means all values were explicit NULLs:
+ expr0 IN (NULL,NULL,..,NULL)
+ @param [OUT] found_type - The bit mask for all found cmp_type()'s.
+ */
+ void all_values_added(Type_handler_hybrid_field_type *compatible,
+ uint *unique_cnt, uint *found_types)
+ {
+ detect_unique_handlers(compatible, unique_cnt, found_types);
+ }
+ /**
+ Creates cmp_item instances for all unique handlers and stores
+ them into m_comparators[].m_cmp_item, using the information previously
+ populated by add_predicant(), add_value() and detect_unque_handlers().
+ */
+ bool make_unique_cmp_items(THD *thd, CHARSET_INFO *cs);
+ void cleanup()
+ {
+ DBUG_ASSERT(m_comparators);
+ for (uint i= 0; i < m_comparator_count; i++)
+ m_comparators[i].cleanup();
+ memset(m_comparators, 0, sizeof(m_comparators[0]) * m_comparator_count);
+ m_comparator_count= 0;
+ m_predicant_index= 0;
+ }
+ bool init_clone(THD *thd, uint nvalues)
+ {
+ m_comparator_count= 0;
+ m_predicant_index= 0;
+ return alloc_comparators(thd, nvalues);
+ }
+ /**
+ @param [IN] args - The argument list that was previously used with
+ add_predicant() and add_value().
+ @param [OUT] idx - In case if a value that is equal to the predicant
+ was found, the index of the matching value is returned
+ here. Otherwise, *idx is not changed.
+ @param [IN/OUT] found_unknown_values - how to handle UNKNOWN results.
+ If found_unknown_values is NULL (e.g. Item_func_case),
+ cmp() returns immediately when the first UNKNOWN
+ result is found.
+ If found_unknown_values is non-NULL (Item_func_in),
+ cmp() does not return when an UNKNOWN result is found,
+ sets *found_unknown_values to true, and continues
+ to compare the remaining pairs to find FALSE
+ (i.e. the value that is equal to the predicant).
+
+ @retval false - Found a value that is equal to the predicant
+ @retval true - Didn't find an equal value
+ */
+ bool cmp(Item_args *args, uint *idx, bool *found_unknown_values)
+ {
+ for (uint i= 0 ; i < m_comparator_count ; i++)
+ {
+ DBUG_ASSERT(m_comparators[i].m_handler != NULL);
+ const int rc= cmp_arg(args, i);
+ if (rc == FALSE)
+ {
+ *idx= m_comparators[i].m_arg_index;
+ return false; // Found a matching value
+ }
+ if (rc == UNKNOWN)
+ {
+ if (!found_unknown_values)
+ return true;
+ *found_unknown_values= true;
+ }
+ }
+ return true; // Not found
+ }
+
+};
+
+
/*
The class Item_func_case is the CASE ... WHEN ... THEN ... END function
implementation.
@@ -1544,18 +2025,16 @@ public:
function and only comparators for there result types are used.
*/
-class Item_func_case :public Item_func_hybrid_field_type
+class Item_func_case :public Item_func_case_expression,
+ public Predicant_to_list_comparator
{
int first_expr_num, else_expr_num;
- enum Item_result left_cmp_type;
String tmp_value;
uint ncases;
- Item_result cmp_type;
DTCollation cmp_collation;
- cmp_item *cmp_items[6]; /* For all result types */
- cmp_item *case_item;
Item **arg_buffer;
uint m_found_types;
+ bool prepare_predicant_and_values(THD *thd, uint *found_types);
public:
Item_func_case(THD *thd, List<Item> &list, Item *first_expr_arg,
Item *else_expr_arg);
@@ -1566,14 +2045,19 @@ public:
bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
- uint decimal_precision() const;
table_map not_null_tables() const { return 0; }
const char *func_name() const { return "case"; }
enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
virtual void print(String *str, enum_query_type query_type);
Item *find_item(String *str);
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
- void cleanup();
+ void cleanup()
+ {
+ DBUG_ENTER("Item_func_case::cleanup");
+ Item_func::cleanup();
+ Predicant_to_list_comparator::cleanup();
+ DBUG_VOID_RETURN;
+ }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
bool need_parentheses_in_default() { return true; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1583,9 +2067,9 @@ public:
Item_func_case *clone= (Item_func_case *) Item_func::build_clone(thd, mem_root);
if (clone)
{
- clone->case_item= 0;
clone->arg_buffer= 0;
- bzero(&clone->cmp_items, sizeof(cmp_items));
+ if (clone->Predicant_to_list_comparator::init_clone(thd, ncases))
+ return NULL;
}
return clone;
}
@@ -1599,14 +2083,27 @@ public:
The current implementation distinguishes 2 cases:
1) all items in <in value list> are constants and have the same
- result type. This case is handled by in_vector class.
+ result type. This case is handled by in_vector class,
+ implementing fast bisection search.
2) otherwise Item_func_in employs several cmp_item objects to perform
comparisons of in_expr and an item from <in value list>. One cmp_item
object for each result type. Different result types are collected in the
fix_length_and_dec() member function by means of collect_cmp_types()
function.
+
+ Bisection is possible when:
+ 1. All types are similar
+ 2. All expressions in <in value list> are const
+ In the presence of NULLs, the correct result of evaluating this item
+ must be UNKNOWN or FALSE. To achieve that:
+ - If type is scalar, we can use bisection and the "have_null" boolean.
+ - If type is ROW, we will need to scan all of <in value list> when
+ searching, so bisection is impossible. Unless:
+ 3. UNKNOWN and FALSE are equivalent results
+ 4. Neither left expression nor <in value list> contain any NULL value
*/
-class Item_func_in :public Item_func_opt_neg
+class Item_func_in :public Item_func_opt_neg,
+ public Predicant_to_list_comparator
{
/**
Usable if <in value list> is made only of constants. Returns true if one
@@ -1614,6 +2111,20 @@ class Item_func_in :public Item_func_opt_neg
IN ( (-5, (12,NULL)), ... ).
*/
bool list_contains_null();
+ bool all_items_are_consts(Item **items, uint nitems) const
+ {
+ for (uint i= 0; i < nitems; i++)
+ {
+ if (!items[i]->const_item())
+ return false;
+ }
+ return true;
+ }
+ bool prepare_predicant_and_values(THD *thd, uint *found_types);
+ bool check_arguments() const
+ {
+ return check_argument_types_like_args0();
+ }
protected:
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
Field *field, Item *value);
@@ -1632,31 +2143,54 @@ public:
and can be used safely as comparisons for key conditions
*/
bool arg_types_compatible;
- Item_result left_cmp_type;
- cmp_item *cmp_items[6]; /* One cmp_item for each result type */
Item_func_in(THD *thd, List<Item> &list):
- Item_func_opt_neg(thd, list), array(0), have_null(0),
+ Item_func_opt_neg(thd, list),
+ Predicant_to_list_comparator(thd, arg_count - 1),
+ array(0), have_null(0),
arg_types_compatible(FALSE)
- {
- bzero(&cmp_items, sizeof(cmp_items));
- allowed_arg_cols= 0; // Fetch this value from first argument
- }
+ { }
longlong val_int();
bool fix_fields(THD *, Item **);
void fix_length_and_dec();
+ bool compatible_types_scalar_bisection_possible()
+ {
+ DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
+ return all_items_are_consts(args + 1, arg_count - 1); // Bisection #2
+ }
+ bool compatible_types_row_bisection_possible()
+ {
+ DBUG_ASSERT(m_comparator.cmp_type() == ROW_RESULT);
+ return all_items_are_consts(args + 1, arg_count - 1) && // Bisection #2
+ ((is_top_level_item() && !negated) || // Bisection #3
+ (!list_contains_null() && !args[0]->maybe_null)); // Bisection #4
+ }
+ bool agg_all_arg_charsets_for_comparison()
+ {
+ return agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
+ }
+ void fix_in_vector();
+ bool value_list_convert_const_to_int(THD *thd);
+ bool fix_for_scalar_comparison_using_bisection(THD *thd)
+ {
+ array= m_comparator.type_handler()->make_in_vector(thd, this, arg_count - 1);
+ if (!array) // OOM
+ return true;
+ fix_in_vector();
+ return false;
+ }
+ bool fix_for_scalar_comparison_using_cmp_items(THD *thd, uint found_types);
+
+ bool fix_for_row_comparison_using_cmp_items(THD *thd);
+ bool fix_for_row_comparison_using_bisection(THD *thd);
+
void cleanup()
{
- uint i;
DBUG_ENTER("Item_func_in::cleanup");
Item_int_func::cleanup();
delete array;
array= 0;
- for (i= 0; i <= (uint)TIME_RESULT; i++)
- {
- delete cmp_items[i];
- cmp_items[i]= 0;
- }
+ Predicant_to_list_comparator::cleanup();
DBUG_VOID_RETURN;
}
void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
@@ -1670,13 +2204,20 @@ public:
will be replaced to a zero-filled Item_string.
Such a change would require rebuilding of cmp_items.
*/
- Context cmpctx(ANY_SUBST, m_compare_type,
- Item_func_in::compare_collation());
- for (uint i= 0; i < arg_count; i++)
+ if (arg_types_compatible)
+ {
+ Context cmpctx(ANY_SUBST, m_comparator.type_handler(),
+ Item_func_in::compare_collation());
+ args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
+ cond, &args[0]);
+ }
+ for (uint i= 0; i < comparator_count(); i++)
{
- if (arg_types_compatible || i > 0)
- args[i]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
- cond, &args[i]);
+ Context cmpctx(ANY_SUBST, get_comparator_type_handler(i),
+ Item_func_in::compare_collation());
+ uint idx= get_comparator_arg_index(i);
+ args[idx]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
+ cond, &args[idx]);
}
return this;
}
@@ -1695,7 +2236,8 @@ public:
if (clone)
{
clone->array= 0;
- bzero(&clone->cmp_items, sizeof(cmp_items));
+ if (clone->Predicant_to_list_comparator::init_clone(thd, arg_count - 1))
+ return NULL;
}
return clone;
}
@@ -1709,12 +2251,13 @@ public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row();
void store_value(Item *item);
- inline void alloc_comparators();
+ bool alloc_comparators(THD *thd, uint n);
+ bool prepare_comparators(THD *, Item **args, uint arg_count);
int cmp(Item *arg);
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 class Item_func_in;
cmp_item *get_comparator(uint i) { return comparators[i]; }
};
@@ -1727,7 +2270,7 @@ public:
~in_row();
void set(uint pos,Item *item);
uchar *get_value(Item *item);
- friend void Item_func_in::fix_length_and_dec();
+ friend class Item_func_in;
Item_result result_type() { return ROW_RESULT; }
cmp_item *get_cmp_item() { return &tmp; }
};
@@ -1975,7 +2518,7 @@ public:
if ((flags & MY_CS_NOPAD) && !(flags & MY_CS_NON1TO1))
Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST,
- STRING_RESULT,
+ &type_handler_long_blob,
compare_collation()),
cond);
return this;
@@ -2128,12 +2671,19 @@ public:
};
-class Item_func_regexp_instr :public Item_int_func
+/*
+ In the corner case REGEXP_INSTR could return (2^32 + 1),
+ which would not fit into Item_long_func range.
+ But string lengths are limited with max_allowed_packet,
+ which cannot be bigger than 1024*1024*1024.
+*/
+class Item_func_regexp_instr :public Item_long_func
{
Regexp_processor_pcre re;
DTCollation cmp_collation;
public:
- Item_func_regexp_instr(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b)
+ Item_func_regexp_instr(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b)
{}
void cleanup()
{
@@ -2219,7 +2769,6 @@ public:
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
void traverse_cond(Cond_traverser, void *arg, traverse_order order);
void neg_arguments(THD *thd);
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
@@ -2352,14 +2901,15 @@ class Item_equal: public Item_bool_func
bool link_equal_fields;
- Item_result m_compare_type;
+ const Type_handler *m_compare_handler;
CHARSET_INFO *m_compare_collation;
String cmp_value1, cmp_value2;
public:
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
- Item_equal(THD *thd, Item *f1, Item *f2, bool with_const_item);
+ Item_equal(THD *thd, const Type_handler *handler,
+ Item *f1, Item *f2, bool with_const_item);
Item_equal(THD *thd, Item_equal *item_equal);
/* Currently the const item is always the first in the list of equal items */
inline Item* get_const() { return with_const ? equal_items.head() : NULL; }
@@ -2392,7 +2942,7 @@ public:
bool walk(Item_processor processor, bool walk_subquery, void *arg);
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
virtual void print(String *str, enum_query_type query_type);
- Item_result compare_type() const { return m_compare_type; }
+ const Type_handler *compare_type_handler() const { return m_compare_handler; }
CHARSET_INFO *compare_collation() const { return m_compare_collation; }
void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
@@ -2605,6 +3155,61 @@ public:
{ return get_item_copy<Item_func_dyncol_exists>(thd, mem_root, this); }
};
+
+class Item_func_cursor_bool_attr: public Item_bool_func, public Cursor_ref
+{
+public:
+ Item_func_cursor_bool_attr(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_bool_func(thd), Cursor_ref(name, offset)
+ { }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
+ }
+ void print(String *str, enum_query_type query_type)
+ {
+ Cursor_ref::print_func(str, func_name());
+ }
+};
+
+
+class Item_func_cursor_isopen: public Item_func_cursor_bool_attr
+{
+public:
+ Item_func_cursor_isopen(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_func_cursor_bool_attr(thd, name, offset) { }
+ const char *func_name() const { return "%ISOPEN"; }
+ longlong val_int();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_isopen>(thd, mem_root, this); }
+};
+
+
+class Item_func_cursor_found: public Item_func_cursor_bool_attr
+{
+public:
+ Item_func_cursor_found(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_func_cursor_bool_attr(thd, name, offset) { maybe_null= true; }
+ const char *func_name() const { return "%FOUND"; }
+ longlong val_int();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_found>(thd, mem_root, this); }
+};
+
+
+class Item_func_cursor_notfound: public Item_func_cursor_bool_attr
+{
+public:
+ Item_func_cursor_notfound(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_func_cursor_bool_attr(thd, name, offset) { maybe_null= true; }
+ const char *func_name() const { return "%NOTFOUND"; }
+ longlong val_int();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_notfound>(thd, mem_root, this); }
+};
+
+
+
inline bool is_cond_or(Item *item)
{
if (item->type() != Item::COND_ITEM)
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 4730e187ebe..8ab45e5dbe1 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -38,68 +38,6 @@
/*
=============================================================================
- HELPER FUNCTIONS
-=============================================================================
-*/
-
-static const char* item_name(Item *a, String *str)
-{
- if (a->name)
- return a->name;
- str->length(0);
- a->print(str, QT_ORDINARY);
- return str->c_ptr_safe();
-}
-
-
-static void wrong_precision_error(uint errcode, Item *a,
- ulonglong number, uint maximum)
-{
- char buff[1024];
- String buf(buff, sizeof(buff), system_charset_info);
-
- my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
-}
-
-
-/**
- Get precision and scale for a declaration
-
- return
- 0 ok
- 1 error
-*/
-
-bool get_length_and_scale(ulonglong length, ulonglong decimals,
- ulong *out_length, uint *out_decimals,
- uint max_precision, uint max_scale,
- Item *a)
-{
- if (length > (ulonglong) max_precision)
- {
- wrong_precision_error(ER_TOO_BIG_PRECISION, a, length, max_precision);
- return 1;
- }
- if (decimals > (ulonglong) max_scale)
- {
- wrong_precision_error(ER_TOO_BIG_SCALE, a, decimals, max_scale);
- return 1;
- }
-
- *out_decimals= (uint) decimals;
- my_decimal_trim(&length, out_decimals);
- *out_length= (ulong) length;
-
- if (*out_length < *out_decimals)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
- return 1;
- }
- return 0;
-}
-
-/*
-=============================================================================
LOCAL DECLARATIONS
=============================================================================
*/
@@ -115,7 +53,8 @@ bool get_length_and_scale(ulonglong length, ulonglong decimals,
class Create_native_func : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
/**
Builder method, with no arguments.
@@ -124,7 +63,7 @@ public:
@param item_list The function parameters, none of which are named
@return An item representing the function call
*/
- virtual Item *create_native(THD *thd, LEX_STRING name,
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list) = 0;
protected:
@@ -142,7 +81,8 @@ protected:
class Create_func_arg0 : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
/**
Builder method, with no arguments.
@@ -166,7 +106,7 @@ protected:
class Create_func_arg1 : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
/**
Builder method, with one argument.
@@ -191,7 +131,7 @@ protected:
class Create_func_arg2 : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
/**
Builder method, with two arguments.
@@ -217,7 +157,7 @@ protected:
class Create_func_arg3 : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
/**
Builder method, with three arguments.
@@ -244,7 +184,7 @@ protected:
class Create_sp_func : public Create_qfunc
{
public:
- virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ virtual Item *create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name,
bool use_explicit_name, List<Item> *item_list);
static Create_sp_func s_singleton;
@@ -267,7 +207,7 @@ protected:
class Create_func_no_geom : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
/** Singleton. */
static Create_func_no_geom s_singleton;
@@ -413,7 +353,7 @@ protected:
class Create_func_atan : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_atan s_singleton;
@@ -515,6 +455,19 @@ protected:
};
+class Create_func_chr : public Create_func_arg1
+{
+public:
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
+
+ static Create_func_chr s_singleton;
+
+protected:
+ Create_func_chr() {}
+ virtual ~Create_func_chr() {}
+};
+
+
class Create_func_convexhull : public Create_func_arg1
{
public:
@@ -634,7 +587,7 @@ protected:
class Create_func_concat : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_concat s_singleton;
@@ -644,6 +597,19 @@ protected:
};
+class Create_func_concat_operator_oracle : public Create_native_func
+{
+public:
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
+
+ static Create_func_concat_operator_oracle s_singleton;
+
+protected:
+ Create_func_concat_operator_oracle() {}
+ virtual ~Create_func_concat_operator_oracle() {}
+};
+
+
class Create_func_decode_histogram : public Create_func_arg2
{
public:
@@ -660,7 +626,7 @@ protected:
class Create_func_concat_ws : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_concat_ws s_singleton;
@@ -711,6 +677,19 @@ protected:
#endif
+class Create_func_nvl2 : public Create_func_arg3
+{
+public:
+ virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+
+ static Create_func_nvl2 s_singleton;
+
+protected:
+ Create_func_nvl2() {}
+ virtual ~Create_func_nvl2() {}
+};
+
+
class Create_func_conv : public Create_func_arg3
{
public:
@@ -869,19 +848,6 @@ protected:
};
-class Create_func_decode : public Create_func_arg2
-{
-public:
- virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
-
- static Create_func_decode s_singleton;
-
-protected:
- Create_func_decode() {}
- virtual ~Create_func_decode() {}
-};
-
-
class Create_func_degrees : public Create_func_arg1
{
public:
@@ -898,7 +864,7 @@ protected:
class Create_func_des_decrypt : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_des_decrypt s_singleton;
@@ -911,7 +877,7 @@ protected:
class Create_func_des_encrypt : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_des_encrypt s_singleton;
@@ -980,7 +946,7 @@ class Create_func_distance : public Create_func_arg2
class Create_func_elt : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_elt s_singleton;
@@ -1006,7 +972,7 @@ protected:
class Create_func_encrypt : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_encrypt s_singleton;
@@ -1102,7 +1068,7 @@ protected:
class Create_func_export_set : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_export_set s_singleton;
@@ -1130,7 +1096,7 @@ protected:
class Create_func_field : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_field s_singleton;
@@ -1169,7 +1135,7 @@ protected:
class Create_func_format : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_format s_singleton;
@@ -1221,7 +1187,7 @@ protected:
class Create_func_from_unixtime : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_from_unixtime s_singleton;
@@ -1235,7 +1201,7 @@ protected:
class Create_func_geometry_from_text : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_geometry_from_text s_singleton;
@@ -1250,7 +1216,7 @@ protected:
class Create_func_geometry_from_wkb : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_geometry_from_wkb s_singleton;
@@ -1265,7 +1231,7 @@ protected:
class Create_func_geometry_from_json : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_geometry_from_json s_singleton;
@@ -1278,7 +1244,7 @@ protected:
class Create_func_as_geojson : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_as_geojson s_singleton;
@@ -1365,7 +1331,7 @@ protected:
class Create_func_greatest : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_greatest s_singleton;
@@ -1791,7 +1757,7 @@ protected:
class Create_func_json_detailed: public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_detailed s_singleton;
@@ -1856,7 +1822,7 @@ protected:
class Create_func_json_keys: public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_keys s_singleton;
@@ -1869,7 +1835,7 @@ protected:
class Create_func_json_contains: public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_contains s_singleton;
@@ -1882,7 +1848,7 @@ protected:
class Create_func_json_contains_path : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_contains_path s_singleton;
@@ -1895,7 +1861,7 @@ protected:
class Create_func_json_extract : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_extract s_singleton;
@@ -1908,7 +1874,7 @@ protected:
class Create_func_json_search : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_search s_singleton;
@@ -1921,7 +1887,7 @@ protected:
class Create_func_json_array : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_array s_singleton;
@@ -1934,7 +1900,7 @@ protected:
class Create_func_json_array_append : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_array_append s_singleton;
@@ -1947,7 +1913,7 @@ protected:
class Create_func_json_array_insert : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_array_insert s_singleton;
@@ -1960,7 +1926,7 @@ protected:
class Create_func_json_insert : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_insert s_singleton;
@@ -1973,7 +1939,7 @@ protected:
class Create_func_json_set : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_set s_singleton;
@@ -1986,7 +1952,7 @@ protected:
class Create_func_json_replace : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_replace s_singleton;
@@ -1999,7 +1965,7 @@ protected:
class Create_func_json_remove : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_remove s_singleton;
@@ -2012,7 +1978,7 @@ protected:
class Create_func_json_object : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_object s_singleton;
@@ -2025,7 +1991,7 @@ protected:
class Create_func_json_length : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_length s_singleton;
@@ -2038,7 +2004,7 @@ protected:
class Create_func_json_merge : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_json_merge s_singleton;
@@ -2090,7 +2056,7 @@ protected:
class Create_func_last_insert_id : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_last_insert_id s_singleton;
@@ -2116,7 +2082,7 @@ protected:
class Create_func_least : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_least s_singleton;
@@ -2138,6 +2104,18 @@ protected:
virtual ~Create_func_length() {}
};
+class Create_func_octet_length : public Create_func_arg1
+{
+public:
+ virtual Item *create_1_arg(THD *thd, Item *arg1);
+
+ static Create_func_octet_length s_singleton;
+
+protected:
+ Create_func_octet_length() {}
+ virtual ~Create_func_octet_length() {}
+};
+
#ifndef DBUG_OFF
class Create_func_like_range_min : public Create_func_arg2
@@ -2196,7 +2174,7 @@ protected:
class Create_func_locate : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_locate s_singleton;
@@ -2209,7 +2187,7 @@ protected:
class Create_func_log : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_log s_singleton;
@@ -2245,10 +2223,11 @@ protected:
};
-class Create_func_lpad : public Create_func_arg3
+class Create_func_lpad : public Create_native_func
{
public:
- virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
static Create_func_lpad s_singleton;
@@ -2300,7 +2279,7 @@ protected:
class Create_func_make_set : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_make_set s_singleton;
@@ -2313,7 +2292,7 @@ protected:
class Create_func_master_pos_wait : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_master_pos_wait s_singleton;
@@ -2326,7 +2305,7 @@ protected:
class Create_func_master_gtid_wait : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_master_gtid_wait s_singleton;
@@ -2622,7 +2601,7 @@ protected:
class Create_func_rand : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_rand s_singleton;
@@ -2661,7 +2640,7 @@ protected:
class Create_func_round : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_round s_singleton;
@@ -2671,10 +2650,11 @@ protected:
};
-class Create_func_rpad : public Create_func_arg3
+class Create_func_rpad : public Create_native_func
{
public:
- virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
static Create_func_rpad s_singleton;
@@ -3056,7 +3036,7 @@ protected:
class Create_func_unix_timestamp : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_unix_timestamp s_singleton;
@@ -3218,7 +3198,7 @@ protected:
class Create_func_year_week : public Create_native_func
{
public:
- virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
static Create_func_year_week s_singleton;
@@ -3262,7 +3242,7 @@ Create_func_no_geom Create_func_no_geom::s_singleton;
Item*
Create_func_no_geom::create_func(THD * /* unused */,
- LEX_STRING /* unused */,
+ LEX_CSTRING /* unused */,
List<Item> * /* unused */)
{
/* FIXME: error message can't be translated. */
@@ -3274,9 +3254,9 @@ Create_func_no_geom::create_func(THD * /* unused */,
Item*
-Create_qfunc::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_qfunc::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
- LEX_STRING db;
+ LEX_CSTRING db;
if (! thd->db && ! thd->lex->sphead)
{
@@ -3292,14 +3272,14 @@ Create_qfunc::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
the case when a default database exist, see Create_sp_func::create().
*/
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- "FUNCTION", name.str);
+ "FUNCTION", name->str);
return NULL;
}
if (thd->lex->copy_db_to(&db.str, &db.length))
return NULL;
- return create_with_db(thd, db, name, false, item_list);
+ return create_with_db(thd, &db, name, false, item_list);
}
@@ -3307,9 +3287,9 @@ Create_qfunc::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_udf_func Create_udf_func::s_singleton;
Item*
-Create_udf_func::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_udf_func::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
- udf_func *udf= find_udf(name.str, name.length);
+ udf_func *udf= find_udf(name->str, name->length);
DBUG_ASSERT(udf);
return create(thd, udf, item_list);
}
@@ -3417,7 +3397,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list)
Create_sp_func Create_sp_func::s_singleton;
Item*
-Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+Create_sp_func::create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name,
bool use_explicit_name, List<Item> *item_list)
{
int arg_count= 0;
@@ -3436,7 +3416,7 @@ Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
because it can refer to a User Defined Function call.
For a Stored Function however, this has no semantic.
*/
- my_error(ER_WRONG_PARAMETERS_TO_STORED_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMETERS_TO_STORED_FCT, MYF(0), name->str);
return NULL;
}
@@ -3444,7 +3424,6 @@ Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
arg_count= item_list->elements;
qname= new (thd->mem_root) sp_name(db, name, use_explicit_name);
- qname->init_qname(thd);
sp_add_used_routine(lex, thd, qname, TYPE_ENUM_FUNCTION);
if (arg_count > 0)
@@ -3459,11 +3438,11 @@ Create_sp_func::create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
Item*
-Create_native_func::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_native_func::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
if (has_named_parameters(item_list))
{
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3472,7 +3451,7 @@ Create_native_func::create_func(THD *thd, LEX_STRING name, List<Item> *item_list
Item*
-Create_func_arg0::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg0::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
int arg_count= 0;
@@ -3481,7 +3460,7 @@ Create_func_arg0::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
if (arg_count != 0)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3490,7 +3469,7 @@ Create_func_arg0::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg1::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg1::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
int arg_count= 0;
@@ -3499,7 +3478,7 @@ Create_func_arg1::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
if (arg_count != 1)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3507,7 +3486,7 @@ Create_func_arg1::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
if (! param_1->is_autogenerated_name)
{
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3516,7 +3495,7 @@ Create_func_arg1::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg2::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg2::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
int arg_count= 0;
@@ -3525,7 +3504,7 @@ Create_func_arg2::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
if (arg_count != 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3535,7 +3514,7 @@ Create_func_arg2::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
if ( (! param_1->is_autogenerated_name)
|| (! param_2->is_autogenerated_name))
{
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3544,7 +3523,7 @@ Create_func_arg2::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
Item*
-Create_func_arg3::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_arg3::create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
int arg_count= 0;
@@ -3553,7 +3532,7 @@ Create_func_arg3::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
if (arg_count != 3)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3565,7 +3544,7 @@ Create_func_arg3::create_func(THD *thd, LEX_STRING name, List<Item> *item_list)
|| (! param_2->is_autogenerated_name)
|| (! param_3->is_autogenerated_name))
{
- my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3663,7 +3642,7 @@ Create_func_asin::create_1_arg(THD *thd, Item *arg1)
Create_func_atan Create_func_atan::s_singleton;
Item*
-Create_func_atan::create_native(THD *thd, LEX_STRING name,
+Create_func_atan::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item* func= NULL;
@@ -3688,7 +3667,7 @@ Create_func_atan::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -3772,6 +3751,16 @@ Create_func_centroid::create_1_arg(THD *thd, Item *arg1)
}
+Create_func_chr Create_func_chr::s_singleton;
+
+Item*
+Create_func_chr::create_1_arg(THD *thd, Item *arg1)
+{
+ CHARSET_INFO *cs_db= thd->variables.collation_database;
+ return new (thd->mem_root) Item_func_chr(thd, arg1, cs_db);
+}
+
+
Create_func_convexhull Create_func_convexhull::s_singleton;
Item*
@@ -3844,7 +3833,7 @@ Create_func_dyncol_json::create_1_arg(THD *thd, Item *arg1)
Create_func_concat Create_func_concat::s_singleton;
Item*
-Create_func_concat::create_native(THD *thd, LEX_STRING name,
+Create_func_concat::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -3854,11 +3843,34 @@ Create_func_concat::create_native(THD *thd, LEX_STRING name,
if (arg_count < 1)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ return NULL;
+ }
+
+ return thd->variables.sql_mode & MODE_ORACLE ?
+ new (thd->mem_root) Item_func_concat_operator_oracle(thd, *item_list) :
+ new (thd->mem_root) Item_func_concat(thd, *item_list);
+}
+
+Create_func_concat_operator_oracle
+ Create_func_concat_operator_oracle::s_singleton;
+
+Item*
+Create_func_concat_operator_oracle::create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list)
+{
+ int arg_count= 0;
+
+ if (item_list != NULL)
+ arg_count= item_list->elements;
+
+ if (arg_count < 1)
+ {
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
- return new (thd->mem_root) Item_func_concat(thd, *item_list);
+ return new (thd->mem_root) Item_func_concat_operator_oracle(thd, *item_list);
}
Create_func_decode_histogram Create_func_decode_histogram::s_singleton;
@@ -3872,7 +3884,7 @@ Create_func_decode_histogram::create_2_arg(THD *thd, Item *arg1, Item *arg2)
Create_func_concat_ws Create_func_concat_ws::s_singleton;
Item*
-Create_func_concat_ws::create_native(THD *thd, LEX_STRING name,
+Create_func_concat_ws::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -3883,7 +3895,7 @@ Create_func_concat_ws::create_native(THD *thd, LEX_STRING name,
/* "WS" stands for "With Separator": this function takes 2+ arguments */
if (arg_count < 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -3932,6 +3944,15 @@ Create_func_contains::create_2_arg(THD *thd, Item *arg1, Item *arg2)
#endif
+Create_func_nvl2 Create_func_nvl2::s_singleton;
+
+Item*
+Create_func_nvl2::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+{
+ return new (thd->mem_root) Item_func_nvl2(thd, arg1, arg2, arg3);
+}
+
+
Create_func_conv Create_func_conv::s_singleton;
Item*
@@ -4046,15 +4067,6 @@ Create_func_dayofyear::create_1_arg(THD *thd, Item *arg1)
}
-Create_func_decode Create_func_decode::s_singleton;
-
-Item*
-Create_func_decode::create_2_arg(THD *thd, Item *arg1, Item *arg2)
-{
- return new (thd->mem_root) Item_func_decode(thd, arg1, arg2);
-}
-
-
Create_func_degrees Create_func_degrees::s_singleton;
Item*
@@ -4068,7 +4080,7 @@ Create_func_degrees::create_1_arg(THD *thd, Item *arg1)
Create_func_des_decrypt Create_func_des_decrypt::s_singleton;
Item*
-Create_func_des_decrypt::create_native(THD *thd, LEX_STRING name,
+Create_func_des_decrypt::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4093,7 +4105,7 @@ Create_func_des_decrypt::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4105,7 +4117,7 @@ Create_func_des_decrypt::create_native(THD *thd, LEX_STRING name,
Create_func_des_encrypt Create_func_des_encrypt::s_singleton;
Item*
-Create_func_des_encrypt::create_native(THD *thd, LEX_STRING name,
+Create_func_des_encrypt::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4130,7 +4142,7 @@ Create_func_des_encrypt::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4184,7 +4196,7 @@ Create_func_distance::create_2_arg(THD *thd, Item *arg1, Item *arg2)
Create_func_elt Create_func_elt::s_singleton;
Item*
-Create_func_elt::create_native(THD *thd, LEX_STRING name,
+Create_func_elt::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -4194,7 +4206,7 @@ Create_func_elt::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -4214,7 +4226,7 @@ Create_func_encode::create_2_arg(THD *thd, Item *arg1, Item *arg2)
Create_func_encrypt Create_func_encrypt::s_singleton;
Item*
-Create_func_encrypt::create_native(THD *thd, LEX_STRING name,
+Create_func_encrypt::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4240,7 +4252,7 @@ Create_func_encrypt::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4315,7 +4327,7 @@ Create_func_exp::create_1_arg(THD *thd, Item *arg1)
Create_func_export_set Create_func_export_set::s_singleton;
Item*
-Create_func_export_set::create_native(THD *thd, LEX_STRING name,
+Create_func_export_set::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4356,7 +4368,7 @@ Create_func_export_set::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4380,7 +4392,7 @@ Create_func_exteriorring::create_1_arg(THD *thd, Item *arg1)
Create_func_field Create_func_field::s_singleton;
Item*
-Create_func_field::create_native(THD *thd, LEX_STRING name,
+Create_func_field::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -4390,7 +4402,7 @@ Create_func_field::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -4419,7 +4431,7 @@ Create_func_floor::create_1_arg(THD *thd, Item *arg1)
Create_func_format Create_func_format::s_singleton;
Item*
-Create_func_format::create_native(THD *thd, LEX_STRING name,
+Create_func_format::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4442,7 +4454,7 @@ Create_func_format::create_native(THD *thd, LEX_STRING name,
break;
}
default:
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
@@ -4484,7 +4496,7 @@ Create_func_from_days::create_1_arg(THD *thd, Item *arg1)
Create_func_from_unixtime Create_func_from_unixtime::s_singleton;
Item*
-Create_func_from_unixtime::create_native(THD *thd, LEX_STRING name,
+Create_func_from_unixtime::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4510,7 +4522,7 @@ Create_func_from_unixtime::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4523,7 +4535,7 @@ Create_func_from_unixtime::create_native(THD *thd, LEX_STRING name,
Create_func_geometry_from_text Create_func_geometry_from_text::s_singleton;
Item*
-Create_func_geometry_from_text::create_native(THD *thd, LEX_STRING name,
+Create_func_geometry_from_text::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4549,7 +4561,7 @@ Create_func_geometry_from_text::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4563,7 +4575,7 @@ Create_func_geometry_from_text::create_native(THD *thd, LEX_STRING name,
Create_func_geometry_from_wkb Create_func_geometry_from_wkb::s_singleton;
Item*
-Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name,
+Create_func_geometry_from_wkb::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4589,7 +4601,7 @@ Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4603,7 +4615,7 @@ Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name,
Create_func_geometry_from_json Create_func_geometry_from_json::s_singleton;
Item*
-Create_func_geometry_from_json::create_native(THD *thd, LEX_STRING name,
+Create_func_geometry_from_json::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4638,7 +4650,7 @@ Create_func_geometry_from_json::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4650,7 +4662,7 @@ Create_func_geometry_from_json::create_native(THD *thd, LEX_STRING name,
Create_func_as_geojson Create_func_as_geojson::s_singleton;
Item*
-Create_func_as_geojson::create_native(THD *thd, LEX_STRING name,
+Create_func_as_geojson::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -4684,7 +4696,7 @@ Create_func_as_geojson::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -4753,7 +4765,7 @@ Create_func_glength::create_1_arg(THD *thd, Item *arg1)
Create_func_greatest Create_func_greatest::s_singleton;
Item*
-Create_func_greatest::create_native(THD *thd, LEX_STRING name,
+Create_func_greatest::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -4763,7 +4775,7 @@ Create_func_greatest::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -5045,7 +5057,7 @@ Create_func_json_exists::create_2_arg(THD *thd, Item *arg1, Item *arg2)
Create_func_json_detailed Create_func_json_detailed::s_singleton;
Item*
-Create_func_json_detailed::create_native(THD *thd, LEX_STRING name,
+Create_func_json_detailed::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5056,7 +5068,7 @@ Create_func_json_detailed::create_native(THD *thd, LEX_STRING name,
if (arg_count < 1 || arg_count > 2 /* json_doc, [path]...*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5162,7 +5174,7 @@ Create_func_last_day::create_1_arg(THD *thd, Item *arg1)
Create_func_json_array Create_func_json_array::s_singleton;
Item*
-Create_func_json_array::create_native(THD *thd, LEX_STRING name,
+Create_func_json_array::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func;
@@ -5183,7 +5195,7 @@ Create_func_json_array::create_native(THD *thd, LEX_STRING name,
Create_func_json_array_append Create_func_json_array_append::s_singleton;
Item*
-Create_func_json_array_append::create_native(THD *thd, LEX_STRING name,
+Create_func_json_array_append::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5194,7 +5206,7 @@ Create_func_json_array_append::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5208,7 +5220,7 @@ Create_func_json_array_append::create_native(THD *thd, LEX_STRING name,
Create_func_json_array_insert Create_func_json_array_insert::s_singleton;
Item*
-Create_func_json_array_insert::create_native(THD *thd, LEX_STRING name,
+Create_func_json_array_insert::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5219,7 +5231,7 @@ Create_func_json_array_insert::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5233,7 +5245,7 @@ Create_func_json_array_insert::create_native(THD *thd, LEX_STRING name,
Create_func_json_insert Create_func_json_insert::s_singleton;
Item*
-Create_func_json_insert::create_native(THD *thd, LEX_STRING name,
+Create_func_json_insert::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5244,7 +5256,7 @@ Create_func_json_insert::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5259,7 +5271,7 @@ Create_func_json_insert::create_native(THD *thd, LEX_STRING name,
Create_func_json_set Create_func_json_set::s_singleton;
Item*
-Create_func_json_set::create_native(THD *thd, LEX_STRING name,
+Create_func_json_set::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5270,7 +5282,7 @@ Create_func_json_set::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5285,7 +5297,7 @@ Create_func_json_set::create_native(THD *thd, LEX_STRING name,
Create_func_json_replace Create_func_json_replace::s_singleton;
Item*
-Create_func_json_replace::create_native(THD *thd, LEX_STRING name,
+Create_func_json_replace::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5296,7 +5308,7 @@ Create_func_json_replace::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5311,7 +5323,7 @@ Create_func_json_replace::create_native(THD *thd, LEX_STRING name,
Create_func_json_remove Create_func_json_remove::s_singleton;
Item*
-Create_func_json_remove::create_native(THD *thd, LEX_STRING name,
+Create_func_json_remove::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5322,7 +5334,7 @@ Create_func_json_remove::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2 /*json_doc, path [,path]*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5336,7 +5348,7 @@ Create_func_json_remove::create_native(THD *thd, LEX_STRING name,
Create_func_json_object Create_func_json_object::s_singleton;
Item*
-Create_func_json_object::create_native(THD *thd, LEX_STRING name,
+Create_func_json_object::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func;
@@ -5347,7 +5359,7 @@ Create_func_json_object::create_native(THD *thd, LEX_STRING name,
arg_count= item_list->elements;
if ((arg_count & 1) != 0 /*is odd*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
func= NULL;
}
else
@@ -5368,7 +5380,7 @@ Create_func_json_object::create_native(THD *thd, LEX_STRING name,
Create_func_json_length Create_func_json_length::s_singleton;
Item*
-Create_func_json_length::create_native(THD *thd, LEX_STRING name,
+Create_func_json_length::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func;
@@ -5377,7 +5389,7 @@ Create_func_json_length::create_native(THD *thd, LEX_STRING name,
if (item_list == NULL ||
(arg_count= item_list->elements) == 0)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
func= NULL;
}
else
@@ -5392,7 +5404,7 @@ Create_func_json_length::create_native(THD *thd, LEX_STRING name,
Create_func_json_merge Create_func_json_merge::s_singleton;
Item*
-Create_func_json_merge::create_native(THD *thd, LEX_STRING name,
+Create_func_json_merge::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func;
@@ -5401,7 +5413,7 @@ Create_func_json_merge::create_native(THD *thd, LEX_STRING name,
if (item_list == NULL ||
(arg_count= item_list->elements) < 2) // json, json
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
func= NULL;
}
else
@@ -5416,7 +5428,7 @@ Create_func_json_merge::create_native(THD *thd, LEX_STRING name,
Create_func_json_contains Create_func_json_contains::s_singleton;
Item*
-Create_func_json_contains::create_native(THD *thd, LEX_STRING name,
+Create_func_json_contains::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5431,7 +5443,7 @@ Create_func_json_contains::create_native(THD *thd, LEX_STRING name,
}
else
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
return func;
@@ -5441,7 +5453,7 @@ Create_func_json_contains::create_native(THD *thd, LEX_STRING name,
Create_func_json_keys Create_func_json_keys::s_singleton;
Item*
-Create_func_json_keys::create_native(THD *thd, LEX_STRING name,
+Create_func_json_keys::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5452,7 +5464,7 @@ Create_func_json_keys::create_native(THD *thd, LEX_STRING name,
if (arg_count < 1 || arg_count > 2 /* json_doc, [path]...*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5466,7 +5478,7 @@ Create_func_json_keys::create_native(THD *thd, LEX_STRING name,
Create_func_json_contains_path Create_func_json_contains_path::s_singleton;
Item*
-Create_func_json_contains_path::create_native(THD *thd, LEX_STRING name,
+Create_func_json_contains_path::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5477,7 +5489,7 @@ Create_func_json_contains_path::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 /* json_doc, one_or_all, path, [path]...*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5491,7 +5503,7 @@ Create_func_json_contains_path::create_native(THD *thd, LEX_STRING name,
Create_func_json_extract Create_func_json_extract::s_singleton;
Item*
-Create_func_json_extract::create_native(THD *thd, LEX_STRING name,
+Create_func_json_extract::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5502,7 +5514,7 @@ Create_func_json_extract::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2 /* json_doc, path, [path]...*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5516,7 +5528,7 @@ Create_func_json_extract::create_native(THD *thd, LEX_STRING name,
Create_func_json_search Create_func_json_search::s_singleton;
Item*
-Create_func_json_search::create_native(THD *thd, LEX_STRING name,
+Create_func_json_search::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5527,7 +5539,7 @@ Create_func_json_search::create_native(THD *thd, LEX_STRING name,
if (arg_count < 3 /* json_doc, one_or_all, search_str, [escape_char[, path]...*/)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
else
{
@@ -5541,7 +5553,7 @@ Create_func_json_search::create_native(THD *thd, LEX_STRING name,
Create_func_last_insert_id Create_func_last_insert_id::s_singleton;
Item*
-Create_func_last_insert_id::create_native(THD *thd, LEX_STRING name,
+Create_func_last_insert_id::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5566,7 +5578,7 @@ Create_func_last_insert_id::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -5587,7 +5599,7 @@ Create_func_lcase::create_1_arg(THD *thd, Item *arg1)
Create_func_least Create_func_least::s_singleton;
Item*
-Create_func_least::create_native(THD *thd, LEX_STRING name,
+Create_func_least::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -5597,7 +5609,7 @@ Create_func_least::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -5610,7 +5622,18 @@ Create_func_length Create_func_length::s_singleton;
Item*
Create_func_length::create_1_arg(THD *thd, Item *arg1)
{
- return new (thd->mem_root) Item_func_length(thd, arg1);
+ if (thd->variables.sql_mode & MODE_ORACLE)
+ return new (thd->mem_root) Item_func_char_length(thd, arg1);
+ else
+ return new (thd->mem_root) Item_func_octet_length(thd, arg1);
+}
+
+Create_func_octet_length Create_func_octet_length::s_singleton;
+
+Item*
+Create_func_octet_length::create_1_arg(THD *thd, Item *arg1)
+{
+ return new (thd->mem_root) Item_func_octet_length(thd, arg1);
}
@@ -5658,7 +5681,7 @@ Create_func_load_file::create_1_arg(THD *thd, Item *arg1)
Create_func_locate Create_func_locate::s_singleton;
Item*
-Create_func_locate::create_native(THD *thd, LEX_STRING name,
+Create_func_locate::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5687,7 +5710,7 @@ Create_func_locate::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -5699,7 +5722,7 @@ Create_func_locate::create_native(THD *thd, LEX_STRING name,
Create_func_log Create_func_log::s_singleton;
Item*
-Create_func_log::create_native(THD *thd, LEX_STRING name,
+Create_func_log::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5724,7 +5747,7 @@ Create_func_log::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -5754,9 +5777,34 @@ Create_func_log2::create_1_arg(THD *thd, Item *arg1)
Create_func_lpad Create_func_lpad::s_singleton;
Item*
-Create_func_lpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_lpad::create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list)
{
- return new (thd->mem_root) Item_func_lpad(thd, arg1, arg2, arg3);
+ Item *func= NULL;
+ int arg_count= item_list ? item_list->elements : 0;
+
+ switch (arg_count) {
+ case 2:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ func= new (thd->mem_root) Item_func_lpad(thd, param_1, param_2);
+ break;
+ }
+ case 3:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ Item *param_3= item_list->pop();
+ func= new (thd->mem_root) Item_func_lpad(thd, param_1, param_2, param_3);
+ break;
+ }
+ default:
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ break;
+ }
+
+ return func;
}
@@ -5790,7 +5838,7 @@ Create_func_maketime::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
Create_func_make_set Create_func_make_set::s_singleton;
Item*
-Create_func_make_set::create_native(THD *thd, LEX_STRING name,
+Create_func_make_set::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= 0;
@@ -5800,7 +5848,7 @@ Create_func_make_set::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return NULL;
}
@@ -5811,7 +5859,7 @@ Create_func_make_set::create_native(THD *thd, LEX_STRING name,
Create_func_master_pos_wait Create_func_master_pos_wait::s_singleton;
Item*
-Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
+Create_func_master_pos_wait::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
@@ -5825,7 +5873,7 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
if (arg_count < 2 || arg_count > 4)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return func;
}
@@ -5862,7 +5910,7 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
Create_func_master_gtid_wait Create_func_master_gtid_wait::s_singleton;
Item*
-Create_func_master_gtid_wait::create_native(THD *thd, LEX_STRING name,
+Create_func_master_gtid_wait::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -5875,7 +5923,7 @@ Create_func_master_gtid_wait::create_native(THD *thd, LEX_STRING name,
if (arg_count < 1 || arg_count > 2)
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
return func;
}
@@ -6108,7 +6156,7 @@ Create_func_radians::create_1_arg(THD *thd, Item *arg1)
Create_func_rand Create_func_rand::s_singleton;
Item*
-Create_func_rand::create_native(THD *thd, LEX_STRING name,
+Create_func_rand::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -6146,7 +6194,7 @@ Create_func_rand::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -6178,7 +6226,7 @@ Create_func_reverse::create_1_arg(THD *thd, Item *arg1)
Create_func_round Create_func_round::s_singleton;
Item*
-Create_func_round::create_native(THD *thd, LEX_STRING name,
+Create_func_round::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -6204,7 +6252,7 @@ Create_func_round::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -6216,9 +6264,34 @@ Create_func_round::create_native(THD *thd, LEX_STRING name,
Create_func_rpad Create_func_rpad::s_singleton;
Item*
-Create_func_rpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_rpad::create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list)
{
- return new (thd->mem_root) Item_func_rpad(thd, arg1, arg2, arg3);
+ Item *func= NULL;
+ int arg_count= item_list ? item_list->elements : 0;
+
+ switch (arg_count) {
+ case 2:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ func= new (thd->mem_root) Item_func_rpad(thd, param_1, param_2);
+ break;
+ }
+ case 3:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ Item *param_3= item_list->pop();
+ func= new (thd->mem_root) Item_func_rpad(thd, param_1, param_2, param_3);
+ break;
+ }
+ default:
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ break;
+ }
+
+ return func;
}
@@ -6487,7 +6560,7 @@ Create_func_unhex::create_1_arg(THD *thd, Item *arg1)
Create_func_unix_timestamp Create_func_unix_timestamp::s_singleton;
Item*
-Create_func_unix_timestamp::create_native(THD *thd, LEX_STRING name,
+Create_func_unix_timestamp::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -6511,7 +6584,7 @@ Create_func_unix_timestamp::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -6642,7 +6715,7 @@ Create_func_y::create_1_arg(THD *thd, Item *arg1)
Create_func_year_week Create_func_year_week::s_singleton;
Item*
-Create_func_year_week::create_native(THD *thd, LEX_STRING name,
+Create_func_year_week::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
@@ -6668,7 +6741,7 @@ Create_func_year_week::create_native(THD *thd, LEX_STRING name,
}
default:
{
- my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
}
@@ -6679,7 +6752,7 @@ Create_func_year_week::create_native(THD *thd, LEX_STRING name,
struct Native_func_registry
{
- LEX_STRING name;
+ LEX_CSTRING name;
Create_func *builder;
};
@@ -6736,11 +6809,13 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("COLUMN_JSON") }, BUILDER(Create_func_dyncol_json)},
{ { C_STRING_WITH_LEN("COMPRESS") }, BUILDER(Create_func_compress)},
{ { C_STRING_WITH_LEN("CONCAT") }, BUILDER(Create_func_concat)},
+ { { C_STRING_WITH_LEN("CONCAT_OPERATOR_ORACLE") }, BUILDER(Create_func_concat_operator_oracle)},
{ { C_STRING_WITH_LEN("CONCAT_WS") }, BUILDER(Create_func_concat_ws)},
{ { C_STRING_WITH_LEN("CONNECTION_ID") }, BUILDER(Create_func_connection_id)},
{ { C_STRING_WITH_LEN("CONV") }, BUILDER(Create_func_conv)},
{ { C_STRING_WITH_LEN("CONVERT_TZ") }, BUILDER(Create_func_convert_tz)},
{ { C_STRING_WITH_LEN("CONVEXHULL") }, GEOM_BUILDER(Create_func_convexhull)},
+ { { C_STRING_WITH_LEN("CHR") }, BUILDER(Create_func_chr)},
{ { C_STRING_WITH_LEN("COS") }, BUILDER(Create_func_cos)},
{ { C_STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)},
{ { C_STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)},
@@ -6751,7 +6826,6 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("DAYOFMONTH") }, BUILDER(Create_func_dayofmonth)},
{ { C_STRING_WITH_LEN("DAYOFWEEK") }, BUILDER(Create_func_dayofweek)},
{ { C_STRING_WITH_LEN("DAYOFYEAR") }, BUILDER(Create_func_dayofyear)},
- { { C_STRING_WITH_LEN("DECODE") }, BUILDER(Create_func_decode)},
{ { C_STRING_WITH_LEN("DEGREES") }, BUILDER(Create_func_degrees)},
{ { C_STRING_WITH_LEN("DECODE_HISTOGRAM") }, BUILDER(Create_func_decode_histogram)},
{ { C_STRING_WITH_LEN("DES_DECRYPT") }, BUILDER(Create_func_des_decrypt)},
@@ -6840,6 +6914,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("LCASE") }, BUILDER(Create_func_lcase)},
{ { C_STRING_WITH_LEN("LEAST") }, BUILDER(Create_func_least)},
{ { C_STRING_WITH_LEN("LENGTH") }, BUILDER(Create_func_length)},
+ { { C_STRING_WITH_LEN("LENGTHB") }, BUILDER(Create_func_octet_length)},
#ifndef DBUG_OFF
{ { C_STRING_WITH_LEN("LIKE_RANGE_MIN") }, BUILDER(Create_func_like_range_min)},
{ { C_STRING_WITH_LEN("LIKE_RANGE_MAX") }, BUILDER(Create_func_like_range_max)},
@@ -6885,12 +6960,14 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("MULTIPOLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { C_STRING_WITH_LEN("MULTIPOLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
{ { C_STRING_WITH_LEN("NAME_CONST") }, BUILDER(Create_func_name_const)},
+ { { C_STRING_WITH_LEN("NVL") }, BUILDER(Create_func_ifnull)},
+ { { C_STRING_WITH_LEN("NVL2") }, BUILDER(Create_func_nvl2)},
{ { C_STRING_WITH_LEN("NULLIF") }, BUILDER(Create_func_nullif)},
{ { C_STRING_WITH_LEN("NUMGEOMETRIES") }, GEOM_BUILDER(Create_func_numgeometries)},
{ { C_STRING_WITH_LEN("NUMINTERIORRINGS") }, GEOM_BUILDER(Create_func_numinteriorring)},
{ { C_STRING_WITH_LEN("NUMPOINTS") }, GEOM_BUILDER(Create_func_numpoints)},
{ { C_STRING_WITH_LEN("OCT") }, BUILDER(Create_func_oct)},
- { { C_STRING_WITH_LEN("OCTET_LENGTH") }, BUILDER(Create_func_length)},
+ { { C_STRING_WITH_LEN("OCTET_LENGTH") }, BUILDER(Create_func_octet_length)},
{ { C_STRING_WITH_LEN("ORD") }, BUILDER(Create_func_ord)},
{ { C_STRING_WITH_LEN("OVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
{ { C_STRING_WITH_LEN("PERIOD_ADD") }, BUILDER(Create_func_period_add)},
@@ -7106,15 +7183,15 @@ void item_create_cleanup()
}
Create_func *
-find_native_function_builder(THD *thd, LEX_STRING name)
+find_native_function_builder(THD *thd, const LEX_CSTRING *name)
{
Native_func_registry *func;
Create_func *builder= NULL;
/* Thread safe */
- func= (Native_func_registry*) my_hash_search(& native_functions_hash,
- (uchar*) name.str,
- name.length);
+ func= (Native_func_registry*) my_hash_search(&native_functions_hash,
+ (uchar*) name->str,
+ name->length);
if (func)
{
@@ -7131,114 +7208,6 @@ find_qualified_function_builder(THD *thd)
}
-Item *
-create_func_cast(THD *thd, Item *a, Cast_target cast_type,
- const char *c_len, const char *c_dec,
- CHARSET_INFO *cs)
-{
- Item *UNINIT_VAR(res);
- ulonglong length= 0, decimals= 0;
- int error;
-
- /*
- We don't have to check for error here as sql_yacc.yy has guaranteed
- that the values are in range of ulonglong
- */
- if (c_len)
- length= (ulonglong) my_strtoll10(c_len, NULL, &error);
- if (c_dec)
- decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
-
- switch (cast_type) {
- case ITEM_CAST_BINARY:
- res= new (thd->mem_root) Item_func_binary(thd, a);
- break;
- case ITEM_CAST_SIGNED_INT:
- res= new (thd->mem_root) Item_func_signed(thd, a);
- break;
- case ITEM_CAST_UNSIGNED_INT:
- res= new (thd->mem_root) Item_func_unsigned(thd, a);
- break;
- case ITEM_CAST_DATE:
- res= new (thd->mem_root) Item_date_typecast(thd, a);
- break;
- case ITEM_CAST_TIME:
- if (decimals > MAX_DATETIME_PRECISION)
- {
- wrong_precision_error(ER_TOO_BIG_PRECISION, a, decimals,
- MAX_DATETIME_PRECISION);
- return 0;
- }
- res= new (thd->mem_root) Item_time_typecast(thd, a, (uint) decimals);
- break;
- case ITEM_CAST_DATETIME:
- if (decimals > MAX_DATETIME_PRECISION)
- {
- wrong_precision_error(ER_TOO_BIG_PRECISION, a, decimals,
- MAX_DATETIME_PRECISION);
- return 0;
- }
- res= new (thd->mem_root) Item_datetime_typecast(thd, a, (uint) decimals);
- break;
- case ITEM_CAST_DECIMAL:
- {
- ulong len;
- uint dec;
- if (get_length_and_scale(length, decimals, &len, &dec,
- DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE,
- a))
- return NULL;
- res= new (thd->mem_root) Item_decimal_typecast(thd, a, len, dec);
- break;
- }
- case ITEM_CAST_DOUBLE:
- {
- ulong len;
- uint dec;
-
- if (!c_len)
- {
- length= DBL_DIG+7;
- decimals= NOT_FIXED_DEC;
- }
- else if (get_length_and_scale(length, decimals, &len, &dec,
- DECIMAL_MAX_PRECISION, NOT_FIXED_DEC-1,
- a))
- return NULL;
- res= new (thd->mem_root) Item_double_typecast(thd, a, (uint) length,
- (uint) decimals);
- break;
- }
- case ITEM_CAST_CHAR:
- {
- int len= -1;
- CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
- if (c_len)
- {
- if (length > MAX_FIELD_BLOBLENGTH)
- {
- char buff[1024];
- String buf(buff, sizeof(buff), system_charset_info);
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), item_name(a, &buf),
- MAX_FIELD_BLOBLENGTH);
- return NULL;
- }
- len= (int) length;
- }
- res= new (thd->mem_root) Item_char_typecast(thd, a, len, real_cs);
- break;
- }
- default:
- {
- DBUG_ASSERT(0);
- res= 0;
- break;
- }
- }
- return res;
-}
-
-
static bool
have_important_literal_warnings(const MYSQL_TIME_STATUS *status)
{
@@ -7396,7 +7365,7 @@ Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
- Cast_target cast_type,
+ const Type_handler *handler,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs)
{
@@ -7404,5 +7373,6 @@ Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
if (!(res= new (thd->mem_root) Item_dyncol_get(thd, str, num)))
return res; // Return NULL
- return create_func_cast(thd, res, cast_type, c_len, c_dec, cs);
+ return handler->create_typecast_item(thd, res,
+ Type_cast_attributes(c_len, c_dec, cs));
}
diff --git a/sql/item_create.h b/sql/item_create.h
index 05fe48f656a..128a19a1c15 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -56,7 +56,7 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call, or NULL
*/
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list) = 0;
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name, List<Item> *item_list) = 0;
protected:
/** Constructor */
@@ -83,7 +83,8 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call
*/
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
/**
The builder create method, for qualified functions.
@@ -94,7 +95,7 @@ public:
@param item_list The list of arguments to the function, can be NULL
@return An item representing the parsed function call
*/
- virtual Item *create_with_db(THD *thd, LEX_STRING db, LEX_STRING name,
+ virtual Item *create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name,
bool use_explicit_name,
List<Item> *item_list) = 0;
@@ -112,7 +113,8 @@ protected:
@param name The native function name
@return The native function builder associated with the name, or NULL
*/
-extern Create_func * find_native_function_builder(THD *thd, LEX_STRING name);
+extern Create_func *find_native_function_builder(THD *thd,
+ const LEX_CSTRING *name);
/**
@@ -131,7 +133,8 @@ extern Create_qfunc * find_qualified_function_builder(THD *thd);
class Create_udf_func : public Create_func
{
public:
- virtual Item *create_func(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item *create_func(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
/**
The builder create method, for User Defined Functions.
@@ -154,20 +157,6 @@ protected:
#endif
-/**
- Builder for cast expressions.
- @param thd The current thread
- @param a The item to cast
- @param cast_type the type casted into
- @param len TODO
- @param dec TODO
- @param cs The character set
-*/
-Item *
-create_func_cast(THD *thd, Item *a, Cast_target cast_type,
- const char *len, const char *dec,
- CHARSET_INFO *cs);
-
Item *create_temporal_literal(THD *thd,
const char *str, uint length,
CHARSET_INFO *cs,
@@ -191,7 +180,7 @@ Item *create_func_dyncol_add(THD *thd, Item *str,
List<DYNCALL_CREATE_DEF> &list);
Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums);
Item *create_func_dyncol_get(THD *thd, Item *num, Item *str,
- Cast_target cast_type,
+ const Type_handler *handler,
const char *c_len, const char *c_dec,
CHARSET_INFO *cs);
Item *create_func_dyncol_json(THD *thd, Item *str);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4a9fa3342e6..b44b29c15a5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -53,12 +53,13 @@
#include "sp.h"
#include "set_var.h"
#include "debug_sync.h"
+#include "sql_base.h"
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {}
#endif
-bool check_reserved_words(LEX_STRING *name)
+bool check_reserved_words(const LEX_CSTRING *name)
{
if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
!my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
@@ -89,23 +90,35 @@ static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2)
}
-void Item_args::set_arguments(THD *thd, List<Item> &list)
+/**
+ Allocate memory for arguments using tmp_args or thd->alloc().
+ @retval false - success
+ @retval true - error (arg_count is set to 0 for conveniece)
+*/
+bool Item_args::alloc_arguments(THD *thd, uint count)
{
- arg_count= list.elements;
- if (arg_count <= 2)
+ if (count <= 2)
{
args= tmp_arg;
+ return false;
}
- else if (!(args= (Item**) thd->alloc(sizeof(Item*) * arg_count)))
+ if ((args= (Item**) thd->alloc(sizeof(Item*) * count)) == NULL)
{
arg_count= 0;
- return;
+ return true;
}
- uint i= 0;
+ return false;
+}
+
+
+void Item_args::set_arguments(THD *thd, List<Item> &list)
+{
+ if (alloc_arguments(thd, list.elements))
+ return;
List_iterator_fast<Item> li(list);
Item *item;
- while ((item= li++))
- args[i++]= item;
+ for (arg_count= 0; (item= li++); )
+ args[arg_count++]= item;
}
@@ -138,6 +151,85 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
}
+bool Item_func::check_argument_types_like_args0() const
+{
+ uint cols;
+ if (arg_count == 0)
+ return false;
+ cols= args[0]->cols();
+ for (uint i= 1; i < arg_count; i++)
+ {
+ if (args[i]->check_cols(cols))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_or_binary(const Type_handler *handler,
+ uint start, uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_or_binary(func_name(), handler))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_traditional_scalar(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_traditional_scalar(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_can_return_int(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_can_return_int(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_can_return_real(uint start,
+ uint end) const
+{
+ for (uint i= start; i < end ; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_can_return_real(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
+bool Item_func::check_argument_types_scalar(uint start, uint end) const
+{
+ for (uint i= start; i < end; i++)
+ {
+ DBUG_ASSERT(i < arg_count);
+ if (args[i]->check_type_scalar(func_name()))
+ return true;
+ }
+ return false;
+}
+
+
/*
Resolve references to table column for a function and its argument
@@ -211,19 +303,6 @@ Item_func::fix_fields(THD *thd, Item **ref)
return TRUE; /* purecov: inspected */
item= *arg;
- if (allowed_arg_cols)
- {
- if (item->check_cols(allowed_arg_cols))
- return 1;
- }
- else
- {
- /* we have to fetch allowed_arg_cols from first argument */
- DBUG_ASSERT(arg == args); // it is first argument
- allowed_arg_cols= item->cols();
- DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
- }
-
if (item->maybe_null)
maybe_null=1;
@@ -234,6 +313,8 @@ Item_func::fix_fields(THD *thd, Item **ref)
with_subselect|= item->has_subquery();
}
}
+ if (check_arguments())
+ return true;
fix_length_and_dec();
if (thd->is_error()) // An error inside fix_length_and_dec occurred
return TRUE;
@@ -528,6 +609,17 @@ my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
}
+bool Item_hybrid_func::fix_attributes(Item **items, uint nitems)
+{
+ bool rc= Item_hybrid_func::type_handler()->
+ Item_hybrid_func_fix_attributes(current_thd,
+ func_name(), this, this,
+ items, nitems);
+ DBUG_ASSERT(!rc || current_thd->is_error());
+ return rc;
+}
+
+
String *Item_real_func::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -568,128 +660,6 @@ void Item_udf_func::fix_num_length_and_dec()
}
-/**
- Count max_length and decimals for temporal functions.
-
- @param item Argument array
- @param nitems Number of arguments in the array.
-
- @retval False on success, true on error.
-*/
-void Item_func::count_datetime_length(enum_field_types field_type_arg,
- Item **item, uint nitems)
-{
- unsigned_flag= 0;
- decimals= 0;
- if (field_type_arg != MYSQL_TYPE_DATE)
- {
- for (uint i= 0; i < nitems; i++)
- set_if_bigger(decimals, item[i]->decimals);
- }
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
- uint len= decimals ? (decimals + 1) : 0;
- len+= mysql_temporal_int_part_length(field_type_arg);
- fix_char_length(len);
-}
-
-/**
- Set max_length/decimals of function if function is fixed point and
- result length/precision depends on argument ones.
-*/
-
-void Item_func::count_decimal_length(Item **item, uint nitems)
-{
- int max_int_part= 0;
- decimals= 0;
- unsigned_flag= 1;
- for (uint i=0 ; i < nitems ; i++)
- {
- set_if_bigger(decimals, item[i]->decimals);
- set_if_bigger(max_int_part, item[i]->decimal_int_part());
- set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
- }
- int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
- fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag));
-}
-
-
-/**
- Set max_length of if it is maximum length of its arguments.
-*/
-
-void Item_func::count_only_length(Item **item, uint nitems)
-{
- uint32 char_length= 0;
- unsigned_flag= 0;
- for (uint i= 0; i < nitems ; i++)
- {
- set_if_bigger(char_length, item[i]->max_char_length());
- set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
- }
- fix_char_length(char_length);
-}
-
-
-/**
- Set max_length/decimals of function if function is floating point and
- result length/precision depends on argument ones.
-*/
-
-void Item_func::count_real_length(Item **items, uint nitems)
-{
- uint32 length= 0;
- decimals= 0;
- max_length= 0;
- unsigned_flag= false;
- for (uint i=0 ; i < nitems ; i++)
- {
- if (decimals < FLOATING_POINT_DECIMALS)
- {
- set_if_bigger(decimals, items[i]->decimals);
- /* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
- set_if_bigger(length, (items[i]->max_length - items[i]->decimals));
- }
- set_if_bigger(max_length, items[i]->max_length);
- }
- if (decimals < FLOATING_POINT_DECIMALS)
- {
- max_length= length;
- length+= decimals;
- if (length < max_length) // If previous operation gave overflow
- max_length= UINT_MAX32;
- else
- max_length= length;
- }
-}
-
-
-/**
- Calculate max_length and decimals for STRING_RESULT functions.
-
- @param field_type Field type.
- @param items Argument array.
- @param nitems Number of arguments.
-
- @retval False on success, true on error.
-*/
-bool Item_func::count_string_result_length(enum_field_types field_type_arg,
- Item **items, uint nitems)
-{
- if (agg_arg_charsets_for_string_result(collation, items, nitems, 1))
- return true;
- if (is_temporal_type(field_type_arg))
- count_datetime_length(field_type_arg, items, nitems);
- else
- {
- count_only_length(items, nitems);
- decimals= max_length ? NOT_FIXED_DEC : 0;
- }
- return false;
-}
-
-
void Item_func::signal_divide_by_null()
{
THD *thd= current_thd;
@@ -728,7 +698,7 @@ String *Item_int_func::val_str(String *str)
void Item_func_connection_id::fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ Item_long_func::fix_length_and_dec();
max_length= 10;
}
@@ -743,404 +713,243 @@ bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
}
-/**
- Check arguments here to determine result's type for a numeric
- function of two arguments.
-*/
-
-void Item_num_op::fix_length_and_dec(void)
+bool Item_num_op::fix_type_handler(const Type_aggregator *aggregator)
{
- DBUG_ENTER("Item_num_op::fix_length_and_dec");
- DBUG_PRINT("info", ("name %s", func_name()));
DBUG_ASSERT(arg_count == 2);
- Item_result r0= args[0]->cast_to_int_type();
- Item_result r1= args[1]->cast_to_int_type();
-
- if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
- r0 == STRING_RESULT || r1 ==STRING_RESULT)
- {
- count_real_length(args, arg_count);
- max_length= float_length(decimals);
- set_handler_by_result_type(REAL_RESULT);
- }
- else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
- r0 == TIME_RESULT || r1 == TIME_RESULT)
- {
- set_handler_by_result_type(DECIMAL_RESULT);
- result_precision();
- fix_decimals();
- if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0)
- set_handler_by_result_type(INT_RESULT);
- }
- else
- {
- DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
- set_handler_by_result_type(INT_RESULT);
- result_precision();
- decimals= 0;
- }
- DBUG_PRINT("info", ("Type: %s",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--")));
- DBUG_VOID_RETURN;
+ const Type_handler *h0= args[0]->cast_to_int_type_handler();
+ const Type_handler *h1= args[1]->cast_to_int_type_handler();
+ if (!aggregate_for_num_op(aggregator, h0, h1))
+ return false;
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ h0->name().ptr(), h1->name().ptr(), func_name());
+ return true;
}
-/**
- Set result type for a numeric function of one argument
- (can be also used by a numeric function of many arguments, if the result
- type depends only on the first argument)
-*/
-
-void Item_func_num1::fix_length_and_dec()
+void Item_func_plus::fix_length_and_dec(void)
{
- DBUG_ENTER("Item_func_num1::fix_length_and_dec");
+ DBUG_ENTER("Item_func_plus::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- // Note, cast_to_int_type() can return TIME_RESULT
- switch (args[0]->cast_to_int_type()) {
- case INT_RESULT:
- set_handler_by_result_type(INT_RESULT);
- max_length= args[0]->max_length;
- unsigned_flag= args[0]->unsigned_flag;
- break;
- case STRING_RESULT:
- case REAL_RESULT:
- set_handler_by_result_type(REAL_RESULT);
- decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
- max_length= float_length(decimals);
- break;
- case TIME_RESULT:
- case DECIMAL_RESULT:
- set_handler_by_result_type(DECIMAL_RESULT);
- decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
- max_length= args[0]->max_length;
- break;
- case ROW_RESULT:
- DBUG_ASSERT(0);
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_plus;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
+ DBUG_ASSERT(aggregator->is_commutative());
+ if (!fix_type_handler(aggregator))
+ {
+ Item_func_plus::type_handler()->Item_func_plus_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
}
- DBUG_PRINT("info", ("Type: %s",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
}
-String *Item_func_hybrid_field_type::val_str(String *str)
+String *Item_func_hybrid_field_type::val_str_from_decimal_op(String *str)
{
- DBUG_ASSERT(fixed == 1);
- switch (Item_func_hybrid_field_type::cmp_type()) {
- case DECIMAL_RESULT:
- {
- my_decimal decimal_value, *val;
- if (!(val= decimal_op_with_null_check(&decimal_value)))
- return 0; // null is set
- my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
- str->set_charset(collation.collation);
- my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
- break;
- }
- case INT_RESULT:
- {
- longlong nr= int_op();
- if (null_value)
- return 0; /* purecov: inspected */
- str->set_int(nr, unsigned_flag, collation.collation);
- break;
- }
- case REAL_RESULT:
- {
- double nr= real_op();
- if (null_value)
- return 0; /* purecov: inspected */
- str->set_real(nr, decimals, collation.collation);
- break;
- }
- case TIME_RESULT:
- {
- MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime) ||
- (null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
- return (String *) 0;
- ltime.time_type= mysql_type_to_time_type(field_type());
- str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
- str->set_charset(&my_charset_bin);
- DBUG_ASSERT(!null_value);
- return str;
- }
- case STRING_RESULT:
- return str_op_with_null_check(&str_value);
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
- DBUG_ASSERT(!null_value || (str == NULL));
+ my_decimal decimal_value, *val;
+ if (!(val= decimal_op_with_null_check(&decimal_value)))
+ return 0; // null is set
+ DBUG_ASSERT(!null_value);
+ my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
+ str->set_charset(collation.collation);
+ my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
return str;
}
-
-double Item_func_hybrid_field_type::val_real()
+double Item_func_hybrid_field_type::val_real_from_decimal_op()
{
- DBUG_ASSERT(fixed == 1);
- switch (Item_func_hybrid_field_type::cmp_type()) {
- case DECIMAL_RESULT:
- {
- my_decimal decimal_value, *val;
- double result;
- if (!(val= decimal_op_with_null_check(&decimal_value)))
- return 0.0; // null is set
- my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
- return result;
- }
- case INT_RESULT:
- {
- longlong result= int_op();
- return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
- }
- case REAL_RESULT:
- return real_op();
- case TIME_RESULT:
- {
- MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime))
- return 0;
- ltime.time_type= mysql_type_to_time_type(field_type());
- return TIME_to_double(&ltime);
- }
- case STRING_RESULT:
- {
- String *res= str_op_with_null_check(&str_value);
- return res ? double_from_string_with_check(res) : 0.0;
- }
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
- return 0.0;
+ my_decimal decimal_value, *val;
+ if (!(val= decimal_op_with_null_check(&decimal_value)))
+ return 0.0; // null is set
+ double result;
+ my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
+ return result;
}
+longlong Item_func_hybrid_field_type::val_int_from_decimal_op()
+{
+ my_decimal decimal_value, *val;
+ if (!(val= decimal_op_with_null_check(&decimal_value)))
+ return 0; // null is set
+ longlong result;
+ my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
+ return result;
+}
-longlong Item_func_hybrid_field_type::val_int()
+bool Item_func_hybrid_field_type::get_date_from_decimal_op(MYSQL_TIME *ltime,
+ ulonglong fuzzydate)
{
- DBUG_ASSERT(fixed == 1);
- switch (Item_func_hybrid_field_type::cmp_type()) {
- case DECIMAL_RESULT:
- {
- my_decimal decimal_value, *val;
- if (!(val= decimal_op_with_null_check(&decimal_value)))
- return 0; // null is set
- longlong result;
- my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
- return result;
- }
- case INT_RESULT:
- return int_op();
- case REAL_RESULT:
- return (longlong) rint(real_op());
- case TIME_RESULT:
- {
- MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime))
- return 0;
- ltime.time_type= mysql_type_to_time_type(field_type());
- return TIME_to_ulonglong(&ltime);
- }
- case STRING_RESULT:
- {
- String *res= str_op_with_null_check(&str_value);
- return res ? longlong_from_string_with_check(res) : 0;
- }
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
- return 0;
+ my_decimal value, *res;
+ if (!(res= decimal_op_with_null_check(&value)) ||
+ decimal_to_datetime_with_warn(res, ltime, fuzzydate,
+ field_name_or_null()))
+ return make_zero_mysql_time(ltime, fuzzydate);
+ return (null_value= 0);
}
-my_decimal *Item_func_hybrid_field_type::val_decimal(my_decimal *decimal_value)
+String *Item_func_hybrid_field_type::val_str_from_int_op(String *str)
{
- my_decimal *val= decimal_value;
- DBUG_ASSERT(fixed == 1);
- switch (Item_func_hybrid_field_type::cmp_type()) {
- case DECIMAL_RESULT:
- val= decimal_op_with_null_check(decimal_value);
- break;
- case INT_RESULT:
- {
- longlong result= int_op();
- if (null_value)
- return NULL;
- int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
- break;
- }
- case REAL_RESULT:
- {
- double result= (double)real_op();
- if (null_value)
- return NULL;
- double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
- break;
- }
- case TIME_RESULT:
- {
- MYSQL_TIME ltime;
- if (date_op_with_null_check(&ltime))
- {
- my_decimal_set_zero(decimal_value);
- return 0;
- }
- ltime.time_type= mysql_type_to_time_type(field_type());
- return date2my_decimal(&ltime, decimal_value);
- }
- case STRING_RESULT:
- {
- String *res= str_op_with_null_check(&str_value);
- return res ? decimal_from_string_with_check(decimal_value, res) : 0;
- }
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
- return val;
+ longlong nr= int_op();
+ if (null_value)
+ return 0; /* purecov: inspected */
+ str->set_int(nr, unsigned_flag, collation.collation);
+ return str;
}
+double Item_func_hybrid_field_type::val_real_from_int_op()
+{
+ longlong result= int_op();
+ return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
+}
-bool Item_func_hybrid_field_type::get_date(MYSQL_TIME *ltime,
- ulonglong fuzzydate)
+my_decimal *
+Item_func_hybrid_field_type::val_decimal_from_int_op(my_decimal *dec)
{
- DBUG_ASSERT(fixed == 1);
- switch (Item_func_hybrid_field_type::cmp_type()) {
- case DECIMAL_RESULT:
- {
- my_decimal value, *res;
- if (!(res= decimal_op_with_null_check(&value)) ||
- decimal_to_datetime_with_warn(res, ltime, fuzzydate,
- field_name_or_null()))
- goto err;
- break;
- }
- case INT_RESULT:
- {
- longlong value= int_op();
- bool neg= !unsigned_flag && value < 0;
- if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
- ltime, fuzzydate,
- field_name_or_null()))
- goto err;
- break;
- }
- case REAL_RESULT:
- {
- double value= real_op();
- if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
- field_name_or_null()))
- goto err;
- break;
- }
- case TIME_RESULT:
- return date_op(ltime,
- fuzzydate |
- (field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0));
- case STRING_RESULT:
- {
- char buff[40];
- String tmp(buff,sizeof(buff), &my_charset_bin),*res;
- if (!(res= str_op_with_null_check(&tmp)) ||
- str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
- ltime, fuzzydate))
- goto err;
- break;
- }
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
+ longlong result= int_op();
+ if (null_value)
+ return NULL;
+ int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, dec);
+ return dec;
+}
+bool Item_func_hybrid_field_type::get_date_from_int_op(MYSQL_TIME *ltime,
+ ulonglong fuzzydate)
+{
+ longlong value= int_op();
+ bool neg= !unsigned_flag && value < 0;
+ if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
+ ltime, fuzzydate,
+ field_name_or_null()))
+ return make_zero_mysql_time(ltime, fuzzydate);
return (null_value= 0);
+}
-err:
- bzero(ltime, sizeof(*ltime));
- return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
+
+String *Item_func_hybrid_field_type::val_str_from_real_op(String *str)
+{
+ double nr= real_op();
+ if (null_value)
+ return 0; /* purecov: inspected */
+ str->set_real(nr, decimals, collation.collation);
+ return str;
}
+longlong Item_func_hybrid_field_type::val_int_from_real_op()
+{
+ return (longlong) rint(real_op());
+}
-void Item_func_signed::print(String *str, enum_query_type query_type)
+my_decimal *
+Item_func_hybrid_field_type::val_decimal_from_real_op(my_decimal *dec)
{
- str->append(STRING_WITH_LEN("cast("));
- args[0]->print(str, query_type);
- str->append(STRING_WITH_LEN(" as signed)"));
+ double result= (double) real_op();
+ if (null_value)
+ return NULL;
+ double2my_decimal(E_DEC_FATAL_ERROR, result, dec);
+ return dec;
+}
+bool Item_func_hybrid_field_type::get_date_from_real_op(MYSQL_TIME *ltime,
+ ulonglong fuzzydate)
+{
+ double value= real_op();
+ if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
+ field_name_or_null()))
+ return make_zero_mysql_time(ltime, fuzzydate);
+ return (null_value= 0);
}
-longlong Item::val_int_from_str(int *error)
+String *Item_func_hybrid_field_type::val_str_from_date_op(String *str)
{
- char buff[MAX_FIELD_WIDTH];
- String tmp(buff,sizeof(buff), &my_charset_bin), *res;
+ MYSQL_TIME ltime;
+ if (date_op_with_null_check(&ltime) ||
+ (null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
+ return (String *) 0;
+ ltime.time_type= mysql_timestamp_type();
+ str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
+ str->set_charset(&my_charset_bin);
+ DBUG_ASSERT(!null_value);
+ return str;
+}
- /*
- For a string result, we must first get the string and then convert it
- to a longlong
- */
+double Item_func_hybrid_field_type::val_real_from_date_op()
+{
+ MYSQL_TIME ltime;
+ if (date_op_with_null_check(&ltime))
+ return 0;
+ ltime.time_type= mysql_timestamp_type();
+ return TIME_to_double(&ltime);
+}
+longlong Item_func_hybrid_field_type::val_int_from_date_op()
+{
+ MYSQL_TIME ltime;
+ if (date_op_with_null_check(&ltime))
+ return 0;
+ ltime.time_type= mysql_timestamp_type();
+ return TIME_to_ulonglong(&ltime);
+}
- if (!(res= val_str(&tmp)))
+my_decimal *
+Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec)
+{
+ MYSQL_TIME ltime;
+ if (date_op_with_null_check(&ltime))
{
- *error= 0;
+ my_decimal_set_zero(dec);
return 0;
}
- Converter_strtoll10_with_warn cnv(NULL, Warn_filter_all(),
- res->charset(), res->ptr(), res->length());
- *error= cnv.error();
- return cnv.result();
+ ltime.time_type= mysql_timestamp_type();
+ return date2my_decimal(&ltime, dec);
}
-longlong Item::val_int_signed_typecast()
+double Item_func_hybrid_field_type::val_real_from_str_op()
{
- if (cast_to_int_type() != STRING_RESULT)
- return val_int();
+ String *res= str_op_with_null_check(&str_value);
+ return res ? double_from_string_with_check(res) : 0.0;
+}
- int error;
- longlong value= val_int_from_str(&error);
- if (!null_value && value < 0 && error == 0)
- push_note_converted_to_negative_complement(current_thd);
- return value;
+longlong Item_func_hybrid_field_type::val_int_from_str_op()
+{
+ String *res= str_op_with_null_check(&str_value);
+ return res ? longlong_from_string_with_check(res) : 0;
}
+my_decimal *
+Item_func_hybrid_field_type::val_decimal_from_str_op(my_decimal *decimal_value)
+{
+ String *res= str_op_with_null_check(&str_value);
+ return res ? decimal_from_string_with_check(decimal_value, res) : 0;
+}
-void Item_func_unsigned::print(String *str, enum_query_type query_type)
+bool Item_func_hybrid_field_type::get_date_from_str_op(MYSQL_TIME *ltime,
+ ulonglong fuzzydate)
+{
+ StringBuffer<40> tmp;
+ String *res;
+ if (!(res= str_op_with_null_check(&tmp)) ||
+ str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
+ ltime, fuzzydate))
+ return make_zero_mysql_time(ltime, fuzzydate);
+ return (null_value= 0);
+}
+
+
+void Item_func_signed::print(String *str, enum_query_type query_type)
{
str->append(STRING_WITH_LEN("cast("));
args[0]->print(str, query_type);
- str->append(STRING_WITH_LEN(" as unsigned)"));
+ str->append(STRING_WITH_LEN(" as signed)"));
}
-longlong Item::val_int_unsigned_typecast()
+void Item_func_unsigned::print(String *str, enum_query_type query_type)
{
- if (cast_to_int_type() == DECIMAL_RESULT)
- {
- longlong value;
- my_decimal tmp, *dec= val_decimal(&tmp);
- if (!null_value)
- my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value);
- else
- value= 0;
- return value;
- }
- else if (cast_to_int_type() != STRING_RESULT)
- {
- longlong value= val_int();
- if (!null_value && unsigned_flag == 0 && value < 0)
- push_note_converted_to_positive_complement(current_thd);
- return value;
- }
+ str->append(STRING_WITH_LEN("cast("));
+ args[0]->print(str, query_type);
+ str->append(STRING_WITH_LEN(" as unsigned)"));
- int error;
- longlong value= val_int_from_str(&error);
- if (!null_value && error < 0)
- push_note_converted_to_positive_complement(current_thd);
- return value;
}
@@ -1209,7 +1018,7 @@ err:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER_THD(thd, ER_WARN_DATA_OUT_OF_RANGE),
- name, 1L);
+ name.str, 1L);
return dec;
}
@@ -1252,7 +1061,7 @@ double Item_double_typecast::val_real()
Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER_THD(thd, ER_WARN_DATA_OUT_OF_RANGE),
- name, 1);
+ name.str, (ulong) 1);
if (error < 0)
{
null_value= 1; // Illegal value
@@ -1395,11 +1204,6 @@ void Item_func_additive_op::result_precision()
DBUG_ASSERT(arg1_int >= 0);
DBUG_ASSERT(arg2_int >= 0);
- /* Integer operations keep unsigned_flag if one of arguments is unsigned */
- if (result_type() == INT_RESULT)
- unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
- else
- unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
unsigned_flag);
}
@@ -1409,16 +1213,30 @@ void Item_func_additive_op::result_precision()
The following function is here to allow the user to force
subtraction of UNSIGNED BIGINT to return negative values.
*/
-
-void Item_func_minus::fix_length_and_dec()
+void Item_func_minus::fix_unsigned_flag()
{
- Item_num_op::fix_length_and_dec();
if (unsigned_flag &&
(current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
unsigned_flag=0;
}
+void Item_func_minus::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_minus::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_minus;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
+ DBUG_ASSERT(!aggregator->is_commutative());
+ if (!fix_type_handler(aggregator))
+ {
+ Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
double Item_func_minus::real_op()
{
double value= args[0]->val_real() - args[1]->val_real();
@@ -1626,13 +1444,8 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
void Item_func_mul::result_precision()
{
- /* Integer operations keep unsigned_flag if one of arguments is unsigned */
- if (result_type() == INT_RESULT)
- unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
- else
- unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
decimals= MY_MIN(args[0]->decimal_scale() + args[1]->decimal_scale(),
- DECIMAL_MAX_SCALE);
+ DECIMAL_MAX_SCALE);
uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
uint precision= MY_MIN(est_prec, DECIMAL_MAX_PRECISION);
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
@@ -1640,6 +1453,22 @@ void Item_func_mul::result_precision()
}
+void Item_func_mul::fix_length_and_dec(void)
+{
+ DBUG_ENTER("Item_func_mul::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mul;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
+ DBUG_ASSERT(aggregator->is_commutative());
+ if (!fix_type_handler(aggregator))
+ {
+ Item_func_mul::type_handler()->Item_func_mul_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
double Item_func_div::real_op()
{
DBUG_ASSERT(fixed == 1);
@@ -1701,53 +1530,51 @@ void Item_func_div::result_precision()
uint precision=MY_MIN(args[0]->decimal_precision() +
args[1]->divisor_precision_increment() + prec_increment,
DECIMAL_MAX_PRECISION);
-
- /* Integer operations keep unsigned_flag if one of arguments is unsigned */
- if (result_type() == INT_RESULT)
- unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
- else
- unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
decimals= MY_MIN(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE);
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
unsigned_flag);
}
-void Item_func_div::fix_length_and_dec()
+void Item_func_div::fix_length_and_dec_double(void)
+{
+ Item_num_op::fix_length_and_dec_double();
+ decimals= MY_MAX(args[0]->decimals, args[1]->decimals) + prec_increment;
+ set_if_smaller(decimals, NOT_FIXED_DEC);
+ uint tmp= float_length(decimals);
+ if (decimals == NOT_FIXED_DEC)
+ max_length= tmp;
+ else
+ {
+ max_length=args[0]->max_length - args[0]->decimals + decimals;
+ set_if_smaller(max_length, tmp);
+ }
+}
+
+
+void Item_func_div::fix_length_and_dec_int(void)
+{
+ set_handler(&type_handler_newdecimal);
+ DBUG_PRINT("info", ("Type changed: %s", type_handler()->name().ptr()));
+ Item_num_op::fix_length_and_dec_decimal();
+}
+
+
+void Item_func_div::fix_length_and_dec(void)
{
DBUG_ENTER("Item_func_div::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
prec_increment= current_thd->variables.div_precincrement;
- Item_num_op::fix_length_and_dec();
- switch (Item_func_div::result_type()) {
- case REAL_RESULT:
+ maybe_null= 1; // devision by zero
+
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_div;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
+ DBUG_ASSERT(!aggregator->is_commutative());
+ if (!fix_type_handler(aggregator))
{
- decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
- set_if_smaller(decimals, NOT_FIXED_DEC);
- uint tmp=float_length(decimals);
- if (decimals == NOT_FIXED_DEC)
- max_length= tmp;
- else
- {
- max_length=args[0]->max_length - args[0]->decimals + decimals;
- set_if_smaller(max_length,tmp);
- }
- break;
- }
- case INT_RESULT:
- set_handler_by_result_type(DECIMAL_RESULT);
- DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
- result_precision();
- break;
- case DECIMAL_RESULT:
- result_precision();
- fix_decimals();
- break;
- case STRING_RESULT:
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
+ Item_func_div::type_handler()->Item_func_div_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
}
- maybe_null= 1; // devision by zero
DBUG_VOID_RETURN;
}
@@ -1920,9 +1747,18 @@ void Item_func_mod::result_precision()
void Item_func_mod::fix_length_and_dec()
{
- Item_num_op::fix_length_and_dec();
- maybe_null= 1;
- unsigned_flag= args[0]->unsigned_flag;
+ DBUG_ENTER("Item_func_mod::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ maybe_null= true; // division by zero
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mod;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
+ DBUG_ASSERT(!aggregator->is_commutative());
+ if (!fix_type_handler(aggregator))
+ {
+ Item_func_mod::type_handler()->Item_func_mod_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ }
+ DBUG_VOID_RETURN;
}
@@ -1969,12 +1805,10 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
}
-void Item_func_neg::fix_length_and_dec()
+void Item_func_neg::fix_length_and_dec_int()
{
- DBUG_ENTER("Item_func_neg::fix_length_and_dec");
- Item_func_num1::fix_length_and_dec();
- /* 1 add because sign can appear */
max_length= args[0]->max_length + 1;
+ set_handler(type_handler_long_or_longlong());
/*
If this is in integer context keep the context as integer if possible
@@ -1982,7 +1816,7 @@ void Item_func_neg::fix_length_and_dec()
Use val() to get value as arg_type doesn't mean that item is
Item_int or Item_float due to existence of Item_param.
*/
- if (Item_func_neg::result_type() == INT_RESULT && args[0]->const_item())
+ if (args[0]->const_item())
{
longlong val= args[0]->val_int();
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
@@ -1997,7 +1831,34 @@ void Item_func_neg::fix_length_and_dec()
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
}
}
- unsigned_flag= 0;
+ unsigned_flag= false;
+}
+
+
+void Item_func_neg::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double);
+ decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length + 1;
+ unsigned_flag= false;
+}
+
+
+void Item_func_neg::fix_length_and_dec_decimal()
+{
+ set_handler(&type_handler_newdecimal);
+ decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length + 1;
+ unsigned_flag= false;
+}
+
+
+void Item_func_neg::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_neg::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ args[0]->cast_to_int_type_handler()->Item_func_neg_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
DBUG_VOID_RETURN;
}
@@ -2038,13 +1899,42 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
}
-void Item_func_abs::fix_length_and_dec()
+void Item_func_abs::fix_length_and_dec_int()
+{
+ max_length= args[0]->max_length;
+ unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
+}
+
+
+void Item_func_abs::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double);
+ decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
+ max_length= float_length(decimals);
+ unsigned_flag= args[0]->unsigned_flag;
+}
+
+
+void Item_func_abs::fix_length_and_dec_decimal()
{
- Item_func_num1::fix_length_and_dec();
+ set_handler(&type_handler_newdecimal);
+ decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length;
unsigned_flag= args[0]->unsigned_flag;
}
+void Item_func_abs::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_abs::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ args[0]->cast_to_int_type_handler()->Item_func_abs_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_VOID_RETURN;
+}
+
+
/** Gateway to natural LOG function. */
double Item_func_ln::val_real()
{
@@ -2273,54 +2163,47 @@ longlong Item_func_bit_neg::val_int()
// Conversion functions
-void Item_func_int_val::fix_length_and_dec()
+void Item_func_int_val::fix_length_and_dec_int_or_decimal()
{
- DBUG_ENTER("Item_func_int_val::fix_length_and_dec");
- DBUG_PRINT("info", ("name %s", func_name()));
-
ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
(args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
- max_length= tmp_max_length > (ulonglong) 4294967295U ?
- (uint32) 4294967295U : (uint32) tmp_max_length;
+ max_length= tmp_max_length > (ulonglong) UINT_MAX32 ?
+ (uint32) UINT_MAX32 : (uint32) tmp_max_length;
uint tmp= float_length(decimals);
set_if_smaller(max_length,tmp);
decimals= 0;
- // Note, cast_to_int_type() can return TIME_RESULT
- switch (args[0]->cast_to_int_type())
+ /*
+ -2 because in most high position can't be used any digit for longlong
+ and one position for increasing value during operation
+ */
+ if (args[0]->max_length - args[0]->decimals >= DECIMAL_LONGLONG_DIGITS - 2)
{
- case STRING_RESULT:
- case REAL_RESULT:
- set_handler_by_result_type(REAL_RESULT);
- max_length= float_length(decimals);
- break;
- case INT_RESULT:
- case TIME_RESULT:
- case DECIMAL_RESULT:
- /*
- -2 because in most high position can't be used any digit for longlong
- and one position for increasing value during operation
- */
- if ((args[0]->max_length - args[0]->decimals) >=
- (DECIMAL_LONGLONG_DIGITS - 2))
- {
- set_handler_by_result_type(DECIMAL_RESULT);
- }
- else
- {
- unsigned_flag= args[0]->unsigned_flag;
- set_handler_by_result_type(INT_RESULT);
- }
- break;
- case ROW_RESULT:
- DBUG_ASSERT(0);
+ set_handler(&type_handler_newdecimal);
}
- DBUG_PRINT("info", ("Type: %s",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--")));
+ else
+ {
+ unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
+ }
+}
+
+void Item_func_int_val::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double);
+ max_length= float_length(0);
+ decimals= 0;
+}
+
+
+void 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()));
+ args[0]->cast_to_int_type_handler()->
+ Item_func_int_val_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
DBUG_VOID_RETURN;
}
@@ -2419,85 +2302,92 @@ my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
}
-void Item_func_round::fix_length_and_dec()
+void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set)
{
- int decimals_to_set;
- longlong val1;
- bool val1_unsigned;
-
+ int decimals_delta= args[0]->decimals - decimals_to_set;
+ int length_increase= (decimals_delta <= 0 || truncate) ? 0 : 1;
+ int precision= args[0]->decimal_precision() + length_increase -
+ decimals_delta;
+ DBUG_ASSERT(decimals_to_set <= DECIMAL_MAX_SCALE);
+ set_handler(&type_handler_newdecimal);
unsigned_flag= args[0]->unsigned_flag;
- if (!args[1]->const_item())
+ decimals= decimals_to_set;
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+}
+
+void Item_func_round::fix_length_and_dec_double(uint decimals_to_set)
+{
+ set_handler(&type_handler_double);
+ unsigned_flag= args[0]->unsigned_flag;
+ decimals= decimals_to_set;
+ max_length= float_length(decimals_to_set);
+}
+
+
+void Item_func_round::fix_arg_decimal()
+{
+ if (args[1]->const_item())
{
- decimals= args[0]->decimals;
- max_length= float_length(decimals);
- if (args[0]->result_type() == DECIMAL_RESULT)
- {
- max_length++;
- set_handler_by_result_type(DECIMAL_RESULT);
- }
+ uint dec= (uint) args[1]->val_uint_from_val_int(DECIMAL_MAX_SCALE);
+ if (args[1]->null_value)
+ fix_length_and_dec_double(NOT_FIXED_DEC);
else
- set_handler_by_result_type(REAL_RESULT);
- return;
+ fix_length_and_dec_decimal(dec);
+ }
+ else
+ {
+ set_handler(&type_handler_newdecimal);
+ unsigned_flag= args[0]->unsigned_flag;
+ decimals= args[0]->decimals;
+ max_length= float_length(args[0]->decimals) + 1;
}
+}
- val1= args[1]->val_int();
- if ((null_value= args[1]->null_value))
- return;
- val1_unsigned= args[1]->unsigned_flag;
- if (val1 < 0)
- decimals_to_set= val1_unsigned ? INT_MAX : 0;
+void Item_func_round::fix_arg_double()
+{
+ if (args[1]->const_item())
+ {
+ uint dec= (uint) args[1]->val_uint_from_val_int(NOT_FIXED_DEC);
+ fix_length_and_dec_double(args[1]->null_value ? NOT_FIXED_DEC : dec);
+ }
else
- decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1;
+ fix_length_and_dec_double(args[0]->decimals);
+}
+
- if (args[0]->decimals == NOT_FIXED_DEC)
+void Item_func_round::fix_arg_int()
+{
+ if (args[1]->const_item())
{
- decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
- max_length= float_length(decimals);
- set_handler_by_result_type(REAL_RESULT);
- return;
- }
-
- switch (args[0]->result_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- set_handler_by_result_type(REAL_RESULT);
- decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
- max_length= float_length(decimals);
- break;
- case INT_RESULT:
- if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
+ longlong val1= args[1]->val_int();
+ bool val1_is_negative= val1 < 0 && !args[1]->unsigned_flag;
+ uint decimals_to_set= val1_is_negative ?
+ 0 : (uint) MY_MIN(val1, DECIMAL_MAX_SCALE);
+ if (args[1]->null_value)
+ fix_length_and_dec_double(NOT_FIXED_DEC);
+ else if ((!decimals_to_set && truncate) ||
+ args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)
{
- int length_can_increase= MY_TEST(!truncate && (val1 < 0) &&
- !val1_unsigned);
+ // Length can increase in some cases: ROUND(9,-1) -> 10
+ int length_can_increase= MY_TEST(!truncate && val1_is_negative);
max_length= args[0]->max_length + length_can_increase;
- /* Here we can keep INT_RESULT */
- set_handler_by_result_type(INT_RESULT);
+ // Here we can keep INT_RESULT
+ unsigned_flag= args[0]->unsigned_flag;
decimals= 0;
- break;
+ set_handler(type_handler_long_or_longlong());
}
- /* fall through */
- case DECIMAL_RESULT:
- {
- set_handler_by_result_type(DECIMAL_RESULT);
- decimals_to_set= MY_MIN(DECIMAL_MAX_SCALE, decimals_to_set);
- int decimals_delta= args[0]->decimals - decimals_to_set;
- int precision= args[0]->decimal_precision();
- int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;
-
- precision-= decimals_delta - length_increase;
- decimals= MY_MIN(decimals_to_set, DECIMAL_MAX_SCALE);
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- break;
- }
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0); /* This result type isn't handled */
+ else
+ fix_length_and_dec_decimal(decimals_to_set);
}
+ else
+ fix_length_and_dec_double(args[0]->decimals);
+
}
+
double my_double_round(double value, longlong dec, bool dec_unsigned,
bool truncate)
{
@@ -2720,122 +2610,17 @@ double Item_func_units::val_real()
}
-void Item_func_min_max::fix_length_and_dec()
+bool Item_func_min_max::fix_attributes(Item **items, uint nitems)
{
- uint unsigned_count= 0;
- int max_int_part=0;
- decimals=0;
- max_length=0;
- maybe_null=0;
- Item_result tmp_cmp_type= args[0]->cmp_type();
- uint string_type_count= 0;
- uint temporal_type_count= 0;
- enum_field_types temporal_field_type= MYSQL_TYPE_DATETIME;
-
- for (uint i=0 ; i < arg_count ; i++)
- {
- set_if_bigger(max_length, args[i]->max_length);
- set_if_bigger(decimals, args[i]->decimals);
- set_if_bigger(max_int_part, args[i]->decimal_int_part());
- unsigned_count+= args[i]->unsigned_flag;
- if (args[i]->maybe_null)
- maybe_null= 1;
- tmp_cmp_type= item_cmp_type(tmp_cmp_type, args[i]->cmp_type());
- string_type_count+= args[i]->cmp_type() == STRING_RESULT;
- if (args[i]->cmp_type() == TIME_RESULT)
- {
- if (!temporal_type_count)
- temporal_field_type= args[i]->field_type();
- else
- temporal_field_type= Field::field_type_merge(temporal_field_type,
- args[i]->field_type());
- temporal_type_count++;
- }
- }
- unsigned_flag= unsigned_count == arg_count; // if all args are unsigned
-
- switch (tmp_cmp_type) {
- case TIME_RESULT:
- // At least one temporal argument was found.
- collation.set_numeric();
- set_handler_by_field_type(temporal_field_type);
- if (is_temporal_type_with_time(temporal_field_type))
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
- else
- decimals= 0;
- break;
-
- case STRING_RESULT:
- /*
- All arguments are of string-alike types:
- CHAR, VARCHAR, TEXT, BINARY, VARBINARY, BLOB, SET, ENUM
- No numeric and no temporal types were found.
- */
- agg_arg_charsets_for_string_result_with_comparison(collation,
- args, arg_count);
- set_handler_by_field_type(agg_field_type(args, arg_count, false));
- break;
-
- case INT_RESULT:
- /*
- All arguments have INT-alike types:
- TINY, SHORT, LONG, LONGLONG, INT24, YEAR, BIT.
- */
- collation.set_numeric();
- fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
- decimals,
- decimals,
- unsigned_flag));
- if (unsigned_count != 0 && unsigned_count != arg_count)
- {
- /*
- If all args are of INT-alike type, but have different unsigned_flag,
- then change type to DECIMAL.
- */
- set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
- }
- else
- {
- /*
- There are only INT-alike arguments with equal unsigned_flag.
- Aggregate types to get the best covering type.
- Treat BIT as LONGLONG when aggregating to non-BIT types.
- Possible final type: TINY, SHORT, LONG, LONGLONG, INT24, YEAR, BIT.
- */
- set_handler_by_field_type(agg_field_type(args, arg_count, true));
- }
- break;
-
- case DECIMAL_RESULT:
- // All arguments are of DECIMAL type
- collation.set_numeric();
- fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
- decimals,
- decimals,
- unsigned_flag));
- set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
- break;
-
- case ROW_RESULT:
- DBUG_ASSERT(0);
- // Pass through
- case REAL_RESULT:
- collation.set_numeric();
- fix_char_length(float_length(decimals));
- /*
- Set type to DOUBLE, as Item_func::create_tmp_field() does not
- distinguish between DOUBLE and FLOAT and always creates Field_double.
- Perhaps we should eventually change this to use agg_field_type() here,
- and fix Item_func::create_tmp_field() to create Field_float when possible.
- */
- set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
- break;
- }
+ bool rc= Item_func_min_max::type_handler()->
+ Item_func_min_max_fix_attributes(current_thd, this, items, nitems);
+ DBUG_ASSERT(!rc || current_thd->is_error());
+ return rc;
}
/*
- Compare item arguments in the DATETIME context.
+ Compare item arguments using DATETIME/DATE/TIME representation.
DESCRIPTION
Compare item arguments as DATETIME values and return the index of the
@@ -2848,21 +2633,11 @@ void Item_func_min_max::fix_length_and_dec()
0 Otherwise
*/
-bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
+bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
longlong UNINIT_VAR(min_max);
DBUG_ASSERT(fixed == 1);
- /*
- just like ::val_int() method of a string item can be called,
- for example, SELECT CONCAT("10", "12") + 1,
- ::get_date() can be called for non-temporal values,
- for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09"))
-
- */
- if (Item_func_min_max::cmp_type() != TIME_RESULT)
- return Item_func::get_date(ltime, fuzzy_date);
-
for (uint i=0; i < arg_count ; i++)
{
longlong res= args[i]->val_temporal_packed(Item_func_min_max::field_type());
@@ -2900,63 +2675,35 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
}
-String *Item_func_min_max::val_str(String *str)
+String *Item_func_min_max::val_str_native(String *str)
{
- DBUG_ASSERT(fixed == 1);
- if (Item_func_min_max::cmp_type() == TIME_RESULT)
- return val_string_from_date(str);
- switch (Item_func_min_max::result_type()) {
- case INT_RESULT:
- return val_string_from_int(str);
- case DECIMAL_RESULT:
- return val_string_from_decimal(str);
- case REAL_RESULT:
- return val_string_from_real(str);
- case STRING_RESULT:
+ String *UNINIT_VAR(res);
+ for (uint i=0; i < arg_count ; i++)
{
- String *UNINIT_VAR(res);
- for (uint i=0; i < arg_count ; i++)
+ if (i == 0)
+ res=args[i]->val_str(str);
+ else
{
- if (i == 0)
- res=args[i]->val_str(str);
- else
+ String *res2;
+ res2= args[i]->val_str(res == str ? &tmp_value : str);
+ if (res2)
{
- String *res2;
- res2= args[i]->val_str(res == str ? &tmp_value : str);
- if (res2)
- {
- int cmp= sortcmp(res,res2,collation.collation);
- if ((cmp_sign < 0 ? cmp : -cmp) < 0)
- res=res2;
- }
+ int cmp= sortcmp(res,res2,collation.collation);
+ if ((cmp_sign < 0 ? cmp : -cmp) < 0)
+ res=res2;
}
- if ((null_value= args[i]->null_value))
- return 0;
}
- res->set_charset(collation.collation);
- return res;
- }
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0); // This case should never be chosen
- return 0;
+ if ((null_value= args[i]->null_value))
+ return 0;
}
- return 0; // Keep compiler happy
+ res->set_charset(collation.collation);
+ return res;
}
-double Item_func_min_max::val_real()
+double Item_func_min_max::val_real_native()
{
- DBUG_ASSERT(fixed == 1);
double value=0.0;
- if (Item_func_min_max::cmp_type() == TIME_RESULT)
- {
- MYSQL_TIME ltime;
- if (get_date(&ltime, 0))
- return 0;
-
- return TIME_to_double(&ltime);
- }
for (uint i=0; i < arg_count ; i++)
{
if (i == 0)
@@ -2974,18 +2721,10 @@ double Item_func_min_max::val_real()
}
-longlong Item_func_min_max::val_int()
+longlong Item_func_min_max::val_int_native()
{
DBUG_ASSERT(fixed == 1);
longlong value=0;
- if (Item_func_min_max::cmp_type() == TIME_RESULT)
- {
- MYSQL_TIME ltime;
- if (get_date(&ltime, 0))
- return 0;
-
- return TIME_to_ulonglong(&ltime);
- }
for (uint i=0; i < arg_count ; i++)
{
if (i == 0)
@@ -3003,19 +2742,11 @@ longlong Item_func_min_max::val_int()
}
-my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
+my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec)
{
DBUG_ASSERT(fixed == 1);
my_decimal tmp_buf, *tmp, *UNINIT_VAR(res);
- if (Item_func_min_max::cmp_type() == TIME_RESULT)
- {
- MYSQL_TIME ltime;
- if (get_date(&ltime, 0))
- return 0;
-
- return date2my_decimal(&ltime, dec);
- }
for (uint i=0; i < arg_count ; i++)
{
if (i == 0)
@@ -3045,7 +2776,15 @@ my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
}
-longlong Item_func_length::val_int()
+longlong Item_func_bit_length::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ String *res= args[0]->val_str(&value);
+ return (null_value= !res) ? 0 : (longlong) res->length() * 8;
+}
+
+
+longlong Item_func_octet_length::val_int()
{
DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
@@ -3081,13 +2820,6 @@ longlong Item_func_coercibility::val_int()
}
-void Item_func_locate::fix_length_and_dec()
-{
- max_length= MY_INT32_NUM_DECIMAL_DIGITS;
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
-}
-
-
longlong Item_func_locate::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -3473,7 +3205,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
!(f_args.maybe_null= (char*) thd->alloc(arg_count * sizeof(char))) ||
!(num_buffer= (char*) thd->alloc(arg_count *
ALIGN_SIZE(sizeof(double)))) ||
- !(f_args.attributes= (char**) thd->alloc(arg_count *
+ !(f_args.attributes= (const char**) thd->alloc(arg_count *
sizeof(char *))) ||
!(f_args.attribute_lengths= (ulong*) thd->alloc(arg_count *
sizeof(long))))
@@ -3503,8 +3235,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
f_args.lengths[i]= arguments[i]->max_length;
f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
- f_args.attributes[i]= arguments[i]->name;
- f_args.attribute_lengths[i]= arguments[i]->name_length;
+ f_args.attributes[i]= arguments[i]->name.str;
+ f_args.attribute_lengths[i]= arguments[i]->name.length;
if (arguments[i]->const_item())
{
@@ -3872,7 +3604,7 @@ longlong Item_master_pos_wait::val_int()
longlong pos = (ulong)args[1]->val_int();
longlong timeout = (arg_count>=3) ? args[2]->val_int() : 0 ;
String connection_name_buff;
- LEX_STRING connection_name;
+ LEX_CSTRING connection_name;
Master_info *mi= NULL;
if (arg_count >= 4)
{
@@ -3880,7 +3612,7 @@ longlong Item_master_pos_wait::val_int()
if (!(con= args[3]->val_str(&connection_name_buff)))
goto err;
- connection_name.str= (char*) con->ptr();
+ connection_name.str= con->ptr();
connection_name.length= con->length();
if (check_master_connection_name(&connection_name))
{
@@ -4580,16 +4312,16 @@ bool Item_func_user_var::check_vcol_func_processor(void *arg)
#define extra_size sizeof(double)
-user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
- bool create_if_not_exists)
+user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
+ bool create_if_not_exists)
{
user_var_entry *entry;
- if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name.str,
- name.length)) &&
+ if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name->str,
+ name->length)) &&
create_if_not_exists)
{
- uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
+ uint size=ALIGN_SIZE(sizeof(user_var_entry))+name->length+1+extra_size;
if (!my_hash_inited(hash))
return 0;
if (!(entry = (user_var_entry*) my_malloc(size,
@@ -4598,7 +4330,7 @@ user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
return 0;
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
extra_size;
- entry->name.length=name.length;
+ entry->name.length=name->length;
entry->value=0;
entry->length=0;
entry->update_query_id=0;
@@ -4616,7 +4348,7 @@ user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
*/
entry->used_query_id=current_thd->query_id;
entry->type=STRING_RESULT;
- memcpy(entry->name.str, name.str, name.length+1);
+ memcpy((char*) entry->name.str, name->str, name->length+1);
if (my_hash_insert(hash,(uchar*) entry))
{
my_free(entry);
@@ -4638,7 +4370,7 @@ bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
{
if (m_var_entry && thd->thread_id == entry_thread_id)
goto end; // update entry->update_query_id for PS
- if (!(m_var_entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
+ if (!(m_var_entry= get_variable(&thd->user_vars, &name, create_if_not_exists)))
{
entry_thread_id= 0;
return TRUE;
@@ -4686,8 +4418,27 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
m_var_entry->set_charset(args[0]->collation.derivation == DERIVATION_NUMERIC ?
default_charset() : args[0]->collation.collation);
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
- set_handler_by_result_type(args[0]->result_type(),
- max_length, collation.collation);
+ switch (args[0]->result_type()) {
+ case STRING_RESULT:
+ case TIME_RESULT:
+ set_handler(type_handler_long_blob.
+ type_handler_adjusted_to_max_octet_length(max_length,
+ collation.collation));
+ break;
+ case REAL_RESULT:
+ set_handler(&type_handler_double);
+ break;
+ case INT_RESULT:
+ set_handler(Type_handler::type_handler_long_or_longlong(max_char_length()));
+ break;
+ case DECIMAL_RESULT:
+ set_handler(&type_handler_newdecimal);
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(0);
+ set_handler(&type_handler_row);
+ break;
+ }
if (thd->lex->current_select)
{
/*
@@ -5020,7 +4771,7 @@ Item_func_set_user_var::check(bool use_result_field)
if (use_result_field && !result_field)
use_result_field= FALSE;
- switch (Item_func_set_user_var::result_type()) {
+ switch (result_type()) {
case REAL_RESULT:
{
save_result.vreal= use_result_field ? result_field->val_real() :
@@ -5113,7 +4864,7 @@ Item_func_set_user_var::update()
bool res= 0;
DBUG_ENTER("Item_func_set_user_var::update");
- switch (Item_func_set_user_var::result_type()) {
+ switch (result_type()) {
case REAL_RESULT:
{
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
@@ -5258,7 +5009,7 @@ void Item_func_set_user_var::print_as_stmt(String *str,
args[0]->print_parenthesised(str, query_type, precedence());
}
-bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
+bool Item_func_set_user_var::send(Protocol *protocol, st_value *buffer)
{
if (result_field)
{
@@ -5266,7 +5017,7 @@ bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
update();
return protocol->store(result_field);
}
- return Item::send(protocol, str_arg);
+ return Item::send(protocol, buffer);
}
void Item_func_set_user_var::make_field(THD *thd, Send_field *tmp_field)
@@ -5275,8 +5026,8 @@ void Item_func_set_user_var::make_field(THD *thd, Send_field *tmp_field)
{
result_field->make_field(tmp_field);
DBUG_ASSERT(tmp_field->table_name != 0);
- if (Item::name)
- tmp_field->col_name=Item::name; // Use user supplied name
+ if (Item::name.str)
+ tmp_field->col_name= Item::name; // Use user supplied name
}
else
Item::make_field(thd, tmp_field);
@@ -5444,7 +5195,7 @@ longlong Item_func_get_user_var::val_int()
static int
get_var_with_binlog(THD *thd, enum_sql_command sql_command,
- LEX_STRING &name, user_var_entry **out_entry)
+ LEX_CSTRING *name, user_var_entry **out_entry)
{
BINLOG_USER_VAR_EVENT *user_var_event;
user_var_entry *var_entry;
@@ -5570,7 +5321,7 @@ void Item_func_get_user_var::fix_length_and_dec()
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- error= get_var_with_binlog(thd, thd->lex->sql_command, name, &m_var_entry);
+ error= get_var_with_binlog(thd, thd->lex->sql_command, &name, &m_var_entry);
/*
If the variable didn't exist it has been created as a STRING-type.
@@ -5583,7 +5334,7 @@ void Item_func_get_user_var::fix_length_and_dec()
max_length= m_var_entry->length;
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
set_handler_by_result_type(m_var_entry->type);
- switch (Item_func_get_user_var::result_type()) {
+ switch (result_type()) {
case REAL_RESULT:
fix_char_length(DBL_DIG + 8);
break;
@@ -5593,7 +5344,6 @@ void Item_func_get_user_var::fix_length_and_dec()
break;
case STRING_RESULT:
max_length= MAX_BLOB_WIDTH - 1;
- set_handler_by_field_type(MYSQL_TYPE_MEDIUM_BLOB);
break;
case DECIMAL_RESULT:
fix_char_length(DECIMAL_MAX_STR_LENGTH);
@@ -5609,7 +5359,7 @@ void Item_func_get_user_var::fix_length_and_dec()
{
collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
null_value= 1;
- set_handler_by_field_type(MYSQL_TYPE_LONG_BLOB);
+ set_handler(&type_handler_long_blob);
max_length= MAX_BLOB_WIDTH;
}
}
@@ -5647,7 +5397,8 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
bool Item_func_get_user_var::set_value(THD *thd,
sp_rcontext * /*ctx*/, Item **it)
{
- Item_func_set_user_var *suv= new (thd->mem_root) Item_func_set_user_var(thd, get_name(), *it);
+ LEX_CSTRING tmp_name= get_name();
+ Item_func_set_user_var *suv= new (thd->mem_root) Item_func_set_user_var(thd, &tmp_name, *it);
/*
Item_func_set_user_var is not fixed after construction, call
fix_fields().
@@ -5661,7 +5412,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
DBUG_ASSERT(fixed == 0);
DBUG_ASSERT(thd->lex->exchange);
if (Item::fix_fields(thd, ref) ||
- !(entry= get_variable(&thd->user_vars, name, 1)))
+ !(entry= get_variable(&thd->user_vars, &name, 1)))
return TRUE;
entry->type= STRING_RESULT;
/*
@@ -5728,7 +5479,7 @@ void Item_user_var_as_out_param::print_for_load(THD *thd, String *str)
Item_func_get_system_var::
Item_func_get_system_var(THD *thd, sys_var *var_arg, enum_var_type var_type_arg,
- LEX_STRING *component_arg, const char *name_arg,
+ LEX_CSTRING *component_arg, const char *name_arg,
size_t name_len_arg):
Item_func(thd), var(var_arg), var_type(var_type_arg),
orig_var_type(var_type_arg), component(*component_arg), cache_present(0)
@@ -5835,8 +5586,8 @@ void Item_func_get_system_var::fix_length_and_dec()
void Item_func_get_system_var::print(String *str, enum_query_type query_type)
{
- if (name_length)
- str->append(name, name_length);
+ if (name.length)
+ str->append(name.str, name.length);
else
{
str->append(STRING_WITH_LEN("@@"));
@@ -5858,34 +5609,8 @@ bool Item_func_get_system_var::check_vcol_func_processor(void *arg)
return mark_unsupported_function("@@", var->name.str, arg, VCOL_SESSION_FUNC);
}
-enum Item_result Item_func_get_system_var::result_type() const
-{
- switch (var->show_type())
- {
- case SHOW_BOOL:
- case SHOW_MY_BOOL:
- case SHOW_SINT:
- case SHOW_SLONG:
- case SHOW_SLONGLONG:
- case SHOW_UINT:
- case SHOW_ULONG:
- case SHOW_ULONGLONG:
- case SHOW_HA_ROWS:
- return INT_RESULT;
- case SHOW_CHAR:
- case SHOW_CHAR_PTR:
- case SHOW_LEX_STRING:
- return STRING_RESULT;
- case SHOW_DOUBLE:
- return REAL_RESULT;
- default:
- my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
- return STRING_RESULT; // keep the compiler happy
- }
-}
-
-enum_field_types Item_func_get_system_var::field_type() const
+const Type_handler *Item_func_get_system_var::type_handler() const
{
switch (var->show_type())
{
@@ -5898,16 +5623,16 @@ enum_field_types Item_func_get_system_var::field_type() const
case SHOW_ULONG:
case SHOW_ULONGLONG:
case SHOW_HA_ROWS:
- return MYSQL_TYPE_LONGLONG;
+ return &type_handler_longlong;
case SHOW_CHAR:
case SHOW_CHAR_PTR:
case SHOW_LEX_STRING:
- return MYSQL_TYPE_VARCHAR;
+ return &type_handler_varchar;
case SHOW_DOUBLE:
- return MYSQL_TYPE_DOUBLE;
+ return &type_handler_double;
default:
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
- return MYSQL_TYPE_VARCHAR; // keep the compiler happy
+ return &type_handler_varchar; // keep the compiler happy
}
}
@@ -6396,11 +6121,11 @@ longlong Item_func_bit_xor::val_int()
*/
-Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
- LEX_STRING component)
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_CSTRING name,
+ LEX_CSTRING component)
{
sys_var *var;
- LEX_STRING *base_name, *component_name;
+ LEX_CSTRING *base_name, *component_name;
if (component.str)
{
@@ -6448,7 +6173,6 @@ Item_func_sp::Item_func_sp(THD *thd, Name_resolution_context *context_arg,
Item_func(thd), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
{
maybe_null= 1;
- m_name->init_qname(thd);
dummy_table= (TABLE*) thd->calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
}
@@ -6460,7 +6184,6 @@ Item_func_sp::Item_func_sp(THD *thd, Name_resolution_context *context_arg,
sp_result_field(NULL)
{
maybe_null= 1;
- m_name->init_qname(thd);
dummy_table= (TABLE*) thd->calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
}
@@ -6505,7 +6228,7 @@ Item_func_sp::func_name() const
}
-void my_missing_function_error(const LEX_STRING &token, const char *func_name)
+void my_missing_function_error(const LEX_CSTRING &token, const char *func_name)
{
if (token.length && is_lex_native_function (&token))
my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
@@ -6535,7 +6258,6 @@ void my_missing_function_error(const LEX_STRING &token, const char *func_name)
bool
Item_func_sp::init_result_field(THD *thd)
{
- LEX_STRING empty_name= { C_STRING_WITH_LEN("") };
TABLE_SHARE *share;
DBUG_ENTER("Item_func_sp::init_result_field");
@@ -6545,7 +6267,7 @@ Item_func_sp::init_result_field(THD *thd)
if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
&thd->sp_func_cache, TRUE)))
{
- my_missing_function_error (m_name->m_name, m_name->m_qname.str);
+ my_missing_function_error (m_name->m_name, ErrConvDQName(m_name).ptr());
context->process_error(thd);
DBUG_RETURN(TRUE);
}
@@ -6561,11 +6283,10 @@ Item_func_sp::init_result_field(THD *thd)
dummy_table->maybe_null = maybe_null;
dummy_table->in_use= thd;
dummy_table->copy_blobs= TRUE;
- share->table_cache_key = empty_name;
- share->table_name = empty_name;
+ share->table_cache_key= empty_clex_str;
+ share->table_name= empty_clex_str;
- if (!(sp_result_field= m_sp->create_result_field(max_length, name,
- dummy_table)))
+ if (!(sp_result_field= m_sp->create_result_field(max_length, &name, dummy_table)))
{
DBUG_RETURN(TRUE);
}
@@ -6595,7 +6316,7 @@ Item_func_sp::init_result_field(THD *thd)
bool Item_func_sp::is_expensive()
{
- return !m_sp->m_chistics->detistic ||
+ return !m_sp->detistic() ||
current_thd->locked_tables_mode < LTM_LOCK_TABLES;
}
@@ -6611,7 +6332,9 @@ void Item_func_sp::fix_length_and_dec()
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
DBUG_ASSERT(sp_result_field);
- Type_std_attributes::set(sp_result_field);
+ Type_std_attributes::set(sp_result_field->type_std_attributes());
+ // There is a bug in the line below. See MDEV-11292 for details.
+ collation.derivation= DERIVATION_COERCIBLE;
maybe_null= 1;
DBUG_VOID_RETURN;
@@ -6667,8 +6390,8 @@ Item_func_sp::execute_impl(THD *thd)
Sub_statement_state statement_state;
Security_context *save_security_ctx= thd->security_ctx;
enum enum_sp_data_access access=
- (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
- SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
+ (m_sp->daccess() == SP_DEFAULT_ACCESS) ?
+ SP_DEFAULT_ACCESS_MAPPING : m_sp->daccess();
DBUG_ENTER("Item_func_sp::execute_impl");
@@ -6685,7 +6408,7 @@ Item_func_sp::execute_impl(THD *thd)
statement-based replication (SBR) is active.
*/
- if (!m_sp->m_chistics->detistic && !trust_function_creators &&
+ if (!m_sp->detistic() && !trust_function_creators &&
(access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
(mysql_bin_log.is_open() &&
thd->variables.binlog_format == BINLOG_FORMAT_STMT))
@@ -6716,29 +6439,26 @@ Item_func_sp::make_field(THD *thd, Send_field *tmp_field)
DBUG_ENTER("Item_func_sp::make_field");
DBUG_ASSERT(sp_result_field);
sp_result_field->make_field(tmp_field);
- if (name)
+ if (name.str)
+ {
+ DBUG_ASSERT(name.length == strlen(name.str));
tmp_field->col_name= name;
+ }
DBUG_VOID_RETURN;
}
-enum enum_field_types
-Item_func_sp::field_type() const
-{
- DBUG_ENTER("Item_func_sp::field_type");
- DBUG_ASSERT(sp_result_field);
- DBUG_RETURN(sp_result_field->type());
-}
-
-Item_result
-Item_func_sp::result_type() const
+const Type_handler *Item_func_sp::type_handler() const
{
- DBUG_ENTER("Item_func_sp::result_type");
+ DBUG_ENTER("Item_func_sp::type_handler");
DBUG_PRINT("info", ("m_sp = %p", (void *) m_sp));
DBUG_ASSERT(sp_result_field);
- DBUG_RETURN(sp_result_field->result_type());
+ // This converts ENUM/SET to STRING
+ const Type_handler *handler= sp_result_field->type_handler();
+ DBUG_RETURN(handler->type_handler_for_item_field());
}
+
longlong Item_func_found_rows::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -6746,6 +6466,34 @@ longlong Item_func_found_rows::val_int()
}
+longlong Item_func_oracle_sql_rowcount::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ THD *thd= current_thd;
+ /*
+ In case when a query like this:
+ INSERT a INTO @va FROM t1;
+ returns multiple rows, SQL%ROWCOUNT should report 1 rather than -1.
+ */
+ longlong rows= thd->get_row_count_func();
+ return rows != -1 ? rows : // ROW_COUNT()
+ thd->found_rows(); // FOUND_ROWS()
+}
+
+
+longlong Item_func_sqlcode::val_int()
+{
+ DBUG_ASSERT(fixed);
+ DBUG_ASSERT(!null_value);
+ Diagnostics_area::Sql_condition_iterator it=
+ current_thd->get_stmt_da()->sql_conditions();
+ const Sql_condition *err;
+ if ((err= it++))
+ return err->get_sql_errno();
+ return 0;
+}
+
+
/**
@brief Checks if requested access to function can be granted to user.
If function isn't found yet, it searches function first.
@@ -6842,7 +6590,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
}
- if (!m_sp->m_chistics->detistic)
+ if (!m_sp->detistic())
{
used_tables_cache |= RAND_TABLE_BIT;
const_item_cache= FALSE;
@@ -6856,7 +6604,7 @@ void Item_func_sp::update_used_tables()
{
Item_func::update_used_tables();
- if (!m_sp->m_chistics->detistic)
+ if (!m_sp->detistic())
{
used_tables_cache |= RAND_TABLE_BIT;
const_item_cache= FALSE;
@@ -6961,4 +6709,269 @@ void Item_func_last_value::fix_length_and_dec()
}
+void Cursor_ref::print_func(String *str, const char *func_name)
+{
+ append_identifier(current_thd, str, m_cursor_name.str, m_cursor_name.length);
+ str->append(func_name);
+}
+
+sp_cursor *Cursor_ref::get_open_cursor_or_error()
+{
+ THD *thd= current_thd;
+ sp_cursor *c= thd->spcont->get_cursor(m_cursor_offset);
+ DBUG_ASSERT(c);
+ if (!c/*safety*/ || !c->is_open())
+ {
+ my_message(ER_SP_CURSOR_NOT_OPEN, ER_THD(thd, ER_SP_CURSOR_NOT_OPEN),
+ MYF(0));
+ return NULL;
+ }
+ return c;
+}
+
+
+longlong Item_func_cursor_isopen::val_int()
+{
+ sp_cursor *c= current_thd->spcont->get_cursor(m_cursor_offset);
+ DBUG_ASSERT(c != NULL);
+ return c ? c->is_open() : 0;
+}
+
+
+longlong Item_func_cursor_found::val_int()
+{
+ sp_cursor *c= get_open_cursor_or_error();
+ return !(null_value= (!c || c->fetch_count() == 0)) && c->found();
+}
+
+
+longlong Item_func_cursor_notfound::val_int()
+{
+ sp_cursor *c= get_open_cursor_or_error();
+ return !(null_value= (!c || c->fetch_count() == 0)) && !c->found();
+}
+
+
+longlong Item_func_cursor_rowcount::val_int()
+{
+ sp_cursor *c= get_open_cursor_or_error();
+ return !(null_value= !c) ? c->row_count() : 0;
+}
+
+/*****************************************************************************
+ SEQUENCE functions
+*****************************************************************************/
+
+longlong Item_func_nextval::val_int()
+{
+ longlong value;
+ int error;
+ const char *key;
+ TABLE *table= table_list->table;
+ uint length= get_table_def_key(table_list, &key);
+ THD *thd= table->in_use;
+ SEQUENCE_LAST_VALUE *entry;
+ char buff[80];
+ String key_buff(buff,sizeof(buff), &my_charset_bin);
+ DBUG_ASSERT(table && table->s->sequence);
+ DBUG_ENTER("Item_func_nextval::val_int");
+
+ if (table->s->tmp_table != NO_TMP_TABLE)
+ {
+ /*
+ Temporary tables has an extra \0 at end to distinguish it from
+ normal tables
+ */
+ key_buff.copy(key, length, &my_charset_bin);
+ key_buff.append((char) 0);
+ key= key_buff.ptr();
+ length++;
+ }
+
+ if (!(entry= ((SEQUENCE_LAST_VALUE*)
+ my_hash_search(&thd->sequences, (uchar*) key, length))))
+ {
+ if (!(key= (char*) my_memdup(key, length, MYF(MY_WME))) ||
+ !(entry= new SEQUENCE_LAST_VALUE((uchar*) key, length)))
+ {
+ /* EOM, error given */
+ my_free((char*) key);
+ delete entry;
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+ if (my_hash_insert(&thd->sequences, (uchar*) entry))
+ {
+ /* EOM, error given */
+ delete entry;
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+ }
+ entry->null_value= null_value= 0;
+ value= table->s->sequence->next_value(table, 0, &error);
+ entry->value= value;
+ entry->set_version(table);
+
+ if (error) // Warning already printed
+ entry->null_value= null_value= 1; // For not strict mode
+ DBUG_RETURN(value);
+}
+
+
+/* Print for nextval and lastval */
+
+void Item_func_nextval::print(String *str, enum_query_type query_type)
+{
+ char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
+ const char *d_name= table_list->db, *t_name= table_list->table_name;
+ bool use_db_name= d_name && d_name[0];
+ THD *thd= current_thd;
+
+ str->append(func_name());
+ str->append('(');
+
+ /*
+ for next_val we assume that table_list has been updated to contain
+ the current db.
+ */
+
+ if (lower_case_table_names > 0)
+ {
+ strmake(t_name_buff, t_name, MAX_ALIAS_NAME-1);
+ my_casedn_str(files_charset_info, t_name_buff);
+ t_name= t_name_buff;
+ if (use_db_name)
+ {
+ strmake(d_name_buff, d_name, MAX_ALIAS_NAME-1);
+ my_casedn_str(files_charset_info, d_name_buff);
+ d_name= d_name_buff;
+ }
+ }
+
+ if (use_db_name)
+ {
+ append_identifier(thd, str, d_name, (uint)strlen(d_name));
+ str->append('.');
+ }
+ append_identifier(thd, str, t_name, (uint) strlen(t_name));
+ str->append(')');
+}
+
+
+/* Return last used value for sequence or NULL if sequence hasn't been used */
+
+longlong Item_func_lastval::val_int()
+{
+ const char *key;
+ SEQUENCE_LAST_VALUE *entry;
+ uint length= get_table_def_key(table_list, &key);
+ THD *thd= table_list->table->in_use;
+ char buff[80];
+ String key_buff(buff,sizeof(buff), &my_charset_bin);
+ DBUG_ENTER("Item_func_lastval::val_int");
+
+ if (table_list->table->s->tmp_table != NO_TMP_TABLE)
+ {
+ /*
+ Temporary tables has an extra \0 at end to distinguish it from
+ normal tables
+ */
+ key_buff.copy(key, length, &my_charset_bin);
+ key_buff.append((char) 0);
+ key= key_buff.ptr();
+ length++;
+ }
+
+ if (!(entry= ((SEQUENCE_LAST_VALUE*)
+ my_hash_search(&thd->sequences, (uchar*) key, length))))
+ {
+ /* Sequence not used */
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+ if (entry->check_version(table_list->table))
+ {
+ /* Table droped and re-created, remove current version */
+ my_hash_delete(&thd->sequences, (uchar*) entry);
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+
+ null_value= entry->null_value;
+ DBUG_RETURN(entry->value);
+}
+
+
+/*
+ Sets next value to be returned from sequences
+
+ SELECT setval('foo', 42, 0); Next nextval will return 43
+ SELECT setval('foo', 42, 0, true); Same as above
+ SELECT setval('foo', 42, 0, false); Next nextval will return 42
+*/
+
+longlong Item_func_setval::val_int()
+{
+ longlong value;
+ int error;
+ TABLE *table= table_list->table;
+ DBUG_ASSERT(table && table->s->sequence);
+ DBUG_ENTER("Item_func_setval::val_int");
+
+ value= nextval;
+ error= table->s->sequence->set_value(table, nextval, round, is_used);
+ if (error)
+ {
+ null_value= 1;
+ value= 0;
+ }
+ DBUG_RETURN(value);
+}
+
+
+/* Print for setval */
+
+void Item_func_setval::print(String *str, enum_query_type query_type)
+{
+ char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
+ const char *d_name= table_list->db, *t_name= table_list->table_name;
+ bool use_db_name= d_name && d_name[0];
+ THD *thd= table_list->table->in_use;
+
+ str->append(func_name());
+ str->append('(');
+
+ /*
+ for next_val we assume that table_list has been updated to contain
+ the current db.
+ */
+
+ if (lower_case_table_names > 0)
+ {
+ strmake(t_name_buff, t_name, MAX_ALIAS_NAME-1);
+ my_casedn_str(files_charset_info, t_name_buff);
+ t_name= t_name_buff;
+ if (use_db_name)
+ {
+ strmake(d_name_buff, d_name, MAX_ALIAS_NAME-1);
+ my_casedn_str(files_charset_info, d_name_buff);
+ d_name= d_name_buff;
+ }
+ }
+
+ if (use_db_name)
+ {
+ append_identifier(thd, str, d_name, (uint)strlen(d_name));
+ str->append('.');
+ }
+ append_identifier(thd, str, t_name, (uint) strlen(t_name));
+ str->append(',');
+ str->append_longlong(nextval);
+ str->append(',');
+ str->append_longlong(is_used);
+ str->append(',');
+ str->append_ulonglong(round);
+ str->append(')');
+}
diff --git a/sql/item_func.h b/sql/item_func.h
index 585b981ba05..8616bdfefc2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -35,21 +35,21 @@ class Item_func :public Item_func_or_sum
{
void sync_with_sum_func_and_with_field(List<Item> &list);
protected:
- /*
- Allowed numbers of columns in result (usually 1, which means scalar value)
- 0 means get this number from first argument
- */
- uint allowed_arg_cols;
String *val_str_from_val_str_ascii(String *str, String *str2);
- void count_only_length(Item **item, uint nitems);
- void count_real_length(Item **item, uint nitems);
- void count_decimal_length(Item **item, uint nitems);
- void count_datetime_length(enum_field_types field_type,
- Item **item, uint nitems);
- bool count_string_result_length(enum_field_types field_type,
- Item **item, uint nitems);
+ virtual bool check_arguments() const
+ {
+ return check_argument_types_scalar(0, arg_count);
+ }
+ bool check_argument_types_like_args0() const;
+ bool check_argument_types_scalar(uint start, uint end) const;
+ bool check_argument_types_traditional_scalar(uint start, uint end) const;
+ bool check_argument_types_or_binary(const Type_handler *handler,
+ uint start, uint end) const;
+ bool check_argument_types_can_return_int(uint start, uint end) const;
+ bool check_argument_types_can_return_real(uint start, uint end) const;
public:
+
table_map not_null_tables_cache;
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
@@ -70,30 +70,30 @@ public:
NEG_FUNC, GSYSVAR_FUNC, DYNCOL_FUNC };
enum Type type() const { return FUNC_ITEM; }
virtual enum Functype functype() const { return UNKNOWN_FUNC; }
- Item_func(THD *thd): Item_func_or_sum(thd), allowed_arg_cols(1)
+ Item_func(THD *thd): Item_func_or_sum(thd)
{
with_sum_func= 0;
with_field= 0;
}
- Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a), allowed_arg_cols(1)
+ Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a)
{
with_sum_func= a->with_sum_func;
with_field= a->with_field;
}
Item_func(THD *thd, Item *a, Item *b):
- Item_func_or_sum(thd, a, b), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b)
{
with_sum_func= a->with_sum_func || b->with_sum_func;
with_field= a->with_field || b->with_field;
}
Item_func(THD *thd, Item *a, Item *b, Item *c):
- Item_func_or_sum(thd, a, b, c), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b, c)
{
with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
with_field= a->with_field || b->with_field || c->with_field;
}
Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
- Item_func_or_sum(thd, a, b, c, d), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b, c, d)
{
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func;
@@ -101,7 +101,7 @@ public:
c->with_field || d->with_field;
}
Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e):
- Item_func_or_sum(thd, a, b, c, d, e), allowed_arg_cols(1)
+ Item_func_or_sum(thd, a, b, c, d, e)
{
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func || e->with_sum_func;
@@ -109,14 +109,13 @@ public:
c->with_field || d->with_field || e->with_field;
}
Item_func(THD *thd, List<Item> &list):
- Item_func_or_sum(thd, list), allowed_arg_cols(1)
+ Item_func_or_sum(thd, list)
{
set_arguments(thd, list);
}
// Constructor used for Item_cond_and/or (see Item comment)
Item_func(THD *thd, Item_func *item):
Item_func_or_sum(thd, item),
- allowed_arg_cols(item->allowed_arg_cols),
not_null_tables_cache(item->not_null_tables_cache)
{
}
@@ -146,7 +145,6 @@ public:
virtual Item *key_item() const { return args[0]; }
void set_arguments(THD *thd, List<Item> &list)
{
- allowed_arg_cols= 1;
Item_args::set_arguments(thd, list);
sync_with_sum_func_and_with_field(list);
list.empty(); // Fields are used
@@ -174,11 +172,7 @@ public:
void signal_divide_by_null();
friend class udf_handler;
Field *create_field_for_create_select(TABLE *table)
- {
- return result_type() != STRING_RESULT ?
- create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) :
- tmp_table_field_from_field_type(table, false, false);
- }
+ { return tmp_table_field_from_field_type(table); }
Item *get_tmp_table_item(THD *thd);
my_decimal *val_decimal(my_decimal *);
@@ -388,8 +382,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value);
longlong val_int()
{ 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; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
void fix_length_and_dec()
{ decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
};
@@ -399,10 +392,11 @@ public:
Functions whose returned field type is determined at fix_fields() time.
*/
class Item_hybrid_func: public Item_func,
- public Type_handler_hybrid_field_type
+ public Type_handler_hybrid_field_type,
+ public Type_geometry_attributes
{
protected:
- void fix_attributes(Item **item, uint nitems);
+ bool fix_attributes(Item **item, uint nitems);
public:
Item_hybrid_func(THD *thd): Item_func(thd) { }
Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { }
@@ -412,12 +406,14 @@ public:
Item_hybrid_func(THD *thd, List<Item> &list): Item_func(thd, list) { }
Item_hybrid_func(THD *thd, Item_hybrid_func *item)
:Item_func(thd, item), Type_handler_hybrid_field_type(item) { }
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+ Field::geometry_type get_geometry_type() const
+ { return Type_geometry_attributes::get_geometry_type(); };
+ void set_geometry_type(uint type)
+ {
+ Type_geometry_attributes::set_geometry_type(type);
+ }
};
@@ -462,6 +458,62 @@ class Item_func_hybrid_field_type: public Item_hybrid_func
DBUG_ASSERT((res != NULL) ^ null_value);
return res;
}
+ bool make_zero_mysql_time(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ bzero(ltime, sizeof(*ltime));
+ return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
+ }
+
+public:
+ // Value methods that involve no conversion
+ String *val_str_from_str_op(String *str)
+ {
+ return str_op_with_null_check(&str_value);
+ }
+ my_decimal *val_decimal_from_decimal_op(my_decimal *dec)
+ {
+ return decimal_op_with_null_check(dec);
+ }
+ longlong val_int_from_int_op()
+ {
+ return int_op();
+ }
+ double val_real_from_real_op()
+ {
+ return real_op();
+ }
+ bool get_date_from_date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ return date_op(ltime,
+ fuzzydate |
+ (field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0));
+ }
+
+ // Value methods that involve conversion
+ String *val_str_from_decimal_op(String *str);
+ String *val_str_from_real_op(String *str);
+ String *val_str_from_int_op(String *str);
+ String *val_str_from_date_op(String *str);
+
+ my_decimal *val_decimal_from_str_op(my_decimal *dec);
+ my_decimal *val_decimal_from_real_op(my_decimal *dec);
+ my_decimal *val_decimal_from_int_op(my_decimal *dec);
+ my_decimal *val_decimal_from_date_op(my_decimal *dec);
+
+ longlong val_int_from_str_op();
+ longlong val_int_from_real_op();
+ longlong val_int_from_decimal_op();
+ longlong val_int_from_date_op();
+
+ double val_real_from_str_op();
+ double val_real_from_decimal_op();
+ double val_real_from_date_op();
+ double val_real_from_int_op();
+
+ bool get_date_from_str_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ bool get_date_from_real_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ bool get_date_from_decimal_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ bool get_date_from_int_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
public:
Item_func_hybrid_field_type(THD *thd):
@@ -480,11 +532,38 @@ public:
Item_hybrid_func(thd, list)
{ collation.set_numeric(); }
- double val_real();
- longlong val_int();
- my_decimal *val_decimal(my_decimal *);
- String *val_str(String*str);
- bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
+ double val_real()
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_hybrid_field_type::type_handler()->
+ Item_func_hybrid_field_type_val_real(this);
+ }
+ longlong val_int()
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_hybrid_field_type::type_handler()->
+ Item_func_hybrid_field_type_val_int(this);
+ }
+ my_decimal *val_decimal(my_decimal *dec)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_hybrid_field_type::type_handler()->
+ Item_func_hybrid_field_type_val_decimal(this, dec);
+ }
+ String *val_str(String*str)
+ {
+ DBUG_ASSERT(fixed);
+ String *res= Item_func_hybrid_field_type::type_handler()->
+ Item_func_hybrid_field_type_val_str(this, str);
+ DBUG_ASSERT(null_value == (res == NULL));
+ return res;
+ }
+ bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_hybrid_field_type::type_handler()->
+ Item_func_hybrid_field_type_get_date(this, res, fuzzy_date);
+ }
/**
@brief Performs the operation that this functions implements when the
@@ -532,6 +611,34 @@ public:
};
+/*
+ This class resembles SQL standard CASE-alike expressions:
+ CASE and its abbreviations COALESCE, NULLIF, IFNULL, IF.
+
+ <case expression> ::= <case abbreviation>
+ | <case specification>
+*/
+class Item_func_case_expression: public Item_func_hybrid_field_type
+{
+public:
+ Item_func_case_expression(THD *thd)
+ :Item_func_hybrid_field_type(thd)
+ { }
+ Item_func_case_expression(THD *thd, Item *a)
+ :Item_func_hybrid_field_type(thd, a)
+ { }
+ Item_func_case_expression(THD *thd, Item *a, Item *b)
+ :Item_func_hybrid_field_type(thd, a, b)
+ { }
+ Item_func_case_expression(THD *thd, Item *a, Item *b, Item *c)
+ :Item_func_hybrid_field_type(thd, a, b, c)
+ { }
+ Item_func_case_expression(THD *thd, List<Item> &list):
+ Item_func_hybrid_field_type(thd, list)
+ { }
+};
+
+
class Item_func_numhybrid: public Item_func_hybrid_field_type
{
protected:
@@ -568,7 +675,8 @@ 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 check_partition_func_processor(void *int_arg) { return FALSE; }
+ bool check_vcol_func_processor(void *arg) { return FALSE; }
};
@@ -583,7 +691,32 @@ class Item_num_op :public Item_func_numhybrid
{
print_op(str, query_type);
}
- void fix_length_and_dec();
+ bool fix_type_handler(const Type_aggregator *aggregator);
+ void fix_length_and_dec_double()
+ {
+ count_real_length(args, arg_count);
+ max_length= float_length(decimals);
+ }
+ void fix_length_and_dec_decimal()
+ {
+ unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
+ result_precision();
+ fix_decimals();
+ }
+ void fix_length_and_dec_int()
+ {
+ unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
+ result_precision();
+ decimals= 0;
+ set_handler(type_handler_long_or_longlong());
+ }
+ void fix_length_and_dec_temporal()
+ {
+ set_handler(&type_handler_newdecimal);
+ fix_length_and_dec_decimal();
+ if (decimals == 0)
+ set_handler(type_handler_long_or_longlong());
+ }
bool need_parentheses_in_default() { return true; }
};
@@ -591,6 +724,12 @@ class Item_num_op :public Item_func_numhybrid
class Item_int_func :public Item_func
{
public:
+ /*
+ QQ: shouldn't 20 characters be enough:
+ Max unsigned = 18,446,744,073,709,551,615 = 20 digits, 20 characters
+ Max signed = 9,223,372,036,854,775,807 = 19 digits, 19 characters
+ Min signed = -9,223,372,036,854,775,808 = 19 digits, 20 characters
+ */
Item_int_func(THD *thd): Item_func(thd)
{ collation.set_numeric(); fix_char_length(21); }
Item_int_func(THD *thd, Item *a): Item_func(thd, a)
@@ -608,18 +747,82 @@ public:
{ collation.set_numeric(); }
double val_real();
String *val_str(String*str);
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const= 0;
void fix_length_and_dec() {}
};
-class Item_func_connection_id :public Item_int_func
+class Item_long_func: public Item_int_func
+{
+public:
+ Item_long_func(THD *thd): Item_int_func(thd) { }
+ Item_long_func(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_long_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_long_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_long_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
+ Item_long_func(THD *thd, Item_long_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_long; }
+ void fix_length_and_dec() { max_length= 11; }
+};
+
+
+class Item_longlong_func: public Item_int_func
+{
+public:
+ Item_longlong_func(THD *thd): Item_int_func(thd) { }
+ Item_longlong_func(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
+ Item_int_func(thd, a, b, c, d) {}
+ Item_longlong_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
+ Item_longlong_func(THD *thd, Item_longlong_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
+};
+
+
+class Cursor_ref
+{
+protected:
+ LEX_CSTRING m_cursor_name;
+ uint m_cursor_offset;
+ class sp_cursor *get_open_cursor_or_error();
+ Cursor_ref(const LEX_CSTRING *name, uint offset)
+ :m_cursor_name(*name), m_cursor_offset(offset)
+ { }
+ void print_func(String *str, const char *func_name);
+};
+
+
+
+class Item_func_cursor_rowcount: public Item_longlong_func,
+ public Cursor_ref
+{
+public:
+ Item_func_cursor_rowcount(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_longlong_func(thd), Cursor_ref(name, offset) { maybe_null= true; }
+ const char *func_name() const { return "%ROWCOUNT"; }
+ longlong val_int();
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
+ }
+ void print(String *str, enum_query_type query_type)
+ {
+ return Cursor_ref::print_func(str, func_name());
+ }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_cursor_rowcount>(thd, mem_root, this); }
+};
+
+
+
+class Item_func_connection_id :public Item_long_func
{
longlong value;
public:
- Item_func_connection_id(THD *thd): Item_int_func(thd) {}
+ Item_func_connection_id(THD *thd): Item_long_func(thd) {}
const char *func_name() const { return "connection_id"; }
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
@@ -641,13 +844,19 @@ public:
unsigned_flag= 0;
}
const char *func_name() const { return "cast_as_signed"; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
longlong val_int()
{
longlong value= args[0]->val_int_signed_typecast();
null_value= args[0]->null_value;
return value;
}
- void fix_length_and_dec()
+ void fix_length_and_dec_double()
+ {
+ fix_char_length(MAX_BIGINT_WIDTH);
+ }
+ void fix_length_and_dec_generic()
{
uint32 char_length= MY_MIN(args[0]->max_char_length(),
MY_INT64_NUM_DECIMAL_DIGITS);
@@ -659,6 +868,23 @@ public:
set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
fix_char_length(char_length);
}
+ void fix_length_and_dec_string()
+ {
+ /*
+ For strings, use decimal_int_part() instead of max_char_length().
+ This is important for Item_hex_hybrid:
+ SELECT CAST(0x1FFFFFFFF AS SIGNED);
+ Length is 5, decimal_int_part() is 13.
+ */
+ uint32 char_length= MY_MIN(args[0]->decimal_int_part(),
+ MY_INT64_NUM_DECIMAL_DIGITS);
+ set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
+ fix_char_length(char_length);
+ }
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
+ }
virtual void print(String *str, enum_query_type query_type);
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool need_parentheses_in_default() { return true; }
@@ -675,12 +901,23 @@ public:
unsigned_flag= 1;
}
const char *func_name() const { return "cast_as_unsigned"; }
+ const Type_handler *type_handler() const
+ {
+ if (max_char_length() <= MY_INT32_NUM_DECIMAL_DIGITS - 1)
+ return &type_handler_long;
+ return &type_handler_longlong;
+ }
longlong val_int()
{
longlong value= args[0]->val_int_unsigned_typecast();
null_value= args[0]->null_value;
return value;
}
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
+ }
+ uint decimal_precision() const { return max_length; }
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_unsigned>(thd, mem_root, this); }
@@ -702,9 +939,12 @@ public:
double val_real();
longlong val_int();
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() {}
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
+ void fix_length_and_dec_generic() {}
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this);
+ }
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; }
@@ -723,8 +963,11 @@ public:
max_length= (uint32) len;
}
double val_real();
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- void fix_length_and_dec() { maybe_null= 1; }
+ void fix_length_and_dec_generic() { maybe_null= 1; }
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
+ }
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; }
@@ -751,6 +994,7 @@ public:
Item_func_additive_op(thd, a, b) {}
const char *func_name() const { return "+"; }
enum precedence precedence() const { return ADD_PRECEDENCE; }
+ void fix_length_and_dec();
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
@@ -769,6 +1013,22 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
void fix_length_and_dec();
+ void fix_unsigned_flag();
+ void fix_length_and_dec_double()
+ {
+ Item_func_additive_op::fix_length_and_dec_double();
+ fix_unsigned_flag();
+ }
+ void fix_length_and_dec_decimal()
+ {
+ Item_func_additive_op::fix_length_and_dec_decimal();
+ fix_unsigned_flag();
+ }
+ void fix_length_and_dec_int()
+ {
+ Item_func_additive_op::fix_length_and_dec_int();
+ fix_unsigned_flag();
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_minus>(thd, mem_root, this); }
};
@@ -785,6 +1045,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
void result_precision();
+ void 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)
@@ -803,6 +1064,8 @@ public:
const char *func_name() const { return "/"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
void fix_length_and_dec();
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_int();
void result_precision();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_div>(thd, mem_root, this); }
@@ -817,6 +1080,8 @@ public:
longlong val_int();
const char *func_name() const { return "DIV"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
void fix_length_and_dec();
void print(String *str, enum_query_type query_type)
{
@@ -842,6 +1107,23 @@ public:
enum precedence precedence() const { return MUL_PRECEDENCE; }
void result_precision();
void fix_length_and_dec();
+ void fix_length_and_dec_double()
+ {
+ Item_num_op::fix_length_and_dec_double();
+ unsigned_flag= args[0]->unsigned_flag;
+ }
+ void fix_length_and_dec_decimal()
+ {
+ Item_num_op::fix_length_and_dec_decimal();
+ unsigned_flag= args[0]->unsigned_flag;
+ }
+ void fix_length_and_dec_int()
+ {
+ max_length= MY_MAX(args[0]->max_length, args[1]->max_length);
+ decimals= 0;
+ unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
+ }
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)
@@ -864,10 +1146,11 @@ public:
str->append(func_name());
args[0]->print_parenthesised(str, query_type, precedence());
}
+ void fix_length_and_dec_int();
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
void 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;}
bool need_parentheses_in_default() { return true; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_neg>(thd, mem_root, this); }
@@ -882,9 +1165,10 @@ public:
longlong int_op();
my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "abs"; }
+ void fix_length_and_dec_int();
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
void 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)
{ return get_item_copy<Item_func_abs>(thd, mem_root, this); }
};
@@ -1057,6 +1341,8 @@ 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_double();
+ void fix_length_and_dec_int_or_decimal();
void fix_length_and_dec();
};
@@ -1069,8 +1355,6 @@ public:
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
- 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)
{ return get_item_copy<Item_func_ceiling>(thd, mem_root, this); }
};
@@ -1084,25 +1368,31 @@ public:
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
- 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)
{ return get_item_copy<Item_func_floor>(thd, mem_root, this); }
};
/* This handles round and truncate */
-class Item_func_round :public Item_func_num1
+class Item_func_round :public Item_func_numhybrid
{
bool truncate;
+ void fix_length_and_dec_decimal(uint decimals_to_set);
+ void fix_length_and_dec_double(uint decimals_to_set);
public:
Item_func_round(THD *thd, Item *a, Item *b, bool trunc_arg)
- :Item_func_num1(thd, a, b), truncate(trunc_arg) {}
+ :Item_func_numhybrid(thd, a, b), truncate(trunc_arg) {}
const char *func_name() const { return truncate ? "truncate" : "round"; }
double real_op();
longlong int_op();
my_decimal *decimal_op(my_decimal *);
- void fix_length_and_dec();
+ void fix_arg_decimal();
+ void fix_arg_int();
+ void fix_arg_double();
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_func_round_fix_length_and_dec(this);
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_round>(thd, mem_root, this); }
};
@@ -1133,11 +1423,13 @@ private:
};
-class Item_func_sign :public Item_int_func
+class Item_func_sign :public Item_long_func
{
public:
- Item_func_sign(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_sign(THD *thd, Item *a): Item_long_func(thd, a) {}
const char *func_name() const { return "sign"; }
+ uint decimal_precision() const { return 1; }
+ void fix_length_and_dec() { fix_char_length(2); }
longlong val_int();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_sign>(thd, mem_root, this); }
@@ -1176,16 +1468,74 @@ class Item_func_min_max :public Item_hybrid_func
{
String tmp_value;
int cmp_sign;
+protected:
+ bool fix_attributes(Item **item, uint nitems);
public:
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
{}
- double val_real();
- longlong val_int();
- String *val_str(String *);
- my_decimal *val_decimal(my_decimal *);
- bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
- void fix_length_and_dec();
+ String *val_str_native(String *str);
+ double val_real_native();
+ longlong val_int_native();
+ my_decimal *val_decimal_native(my_decimal *);
+ bool get_date_native(MYSQL_TIME *res, ulonglong fuzzydate);
+
+ double val_real()
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_real(this);
+ }
+ longlong val_int()
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_int(this);
+ }
+ String *val_str(String *str)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_str(this, str);
+ }
+ my_decimal *val_decimal(my_decimal *dec)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_decimal(this, dec);
+ }
+ bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_get_date(this, res, fuzzy_date);
+ }
+ void aggregate_attributes_real(Item **items, uint nitems)
+ {
+ /*
+ Aggregating attributes for the double data type for LEAST/GREATEST
+ is almost the same with aggregating for CASE-alike hybrid functions,
+ (CASE..THEN, COALESCE, IF, etc).
+ There is one notable difference though, when a numeric argument is mixed
+ with a string argument:
+ - CASE-alike functions return a string data type in such cases
+ COALESCE(10,'x') -> VARCHAR(2) = '10'
+ - LEAST/GREATEST returns double:
+ GREATEST(10,'10e4') -> DOUBLE = 100000
+ As the string argument can represent a number in the scientific notation,
+ like in the example above, max_length of the result can be longer than
+ max_length of the arguments. To handle this properly, max_length is
+ additionally assigned to the result of float_length(decimals).
+ */
+ Item_func::aggregate_attributes_real(items, nitems);
+ max_length= float_length(decimals);
+ }
+ void fix_length_and_dec()
+ {
+ if (aggregate_for_min_max(func_name(), args, arg_count))
+ return;
+ fix_attributes(args, arg_count);
+ }
};
class Item_func_min :public Item_func_min_max
@@ -1218,7 +1568,6 @@ public:
Item_func_rollup_const(THD *thd, Item *a): Item_func(thd, a)
{
name= a->name;
- name_length= a->name_length;
}
double val_real() { return args[0]->val_real(); }
longlong val_int() { return args[0]->val_int(); }
@@ -1226,8 +1575,7 @@ public:
my_decimal *val_decimal(my_decimal *dec) { return args[0]->val_decimal(dec); }
const char *func_name() const { return "rollup_const"; }
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(); }
+ const Type_handler *type_handler() const { return args[0]->type_handler(); }
void fix_length_and_dec()
{
collation= args[0]->collation;
@@ -1241,34 +1589,38 @@ public:
};
-class Item_func_length :public Item_int_func
+class Item_func_octet_length :public Item_long_func
{
String value;
public:
- Item_func_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_octet_length(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
- const char *func_name() const { return "length"; }
+ const char *func_name() const { return "octet_length"; }
void fix_length_and_dec() { max_length=10; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_length>(thd, mem_root, this); }
+ { return get_item_copy<Item_func_octet_length>(thd, mem_root, this); }
};
-class Item_func_bit_length :public Item_func_length
+class Item_func_bit_length :public Item_longlong_func
{
+ String value;
public:
- Item_func_bit_length(THD *thd, Item *a): Item_func_length(thd, a) {}
- longlong val_int()
- { DBUG_ASSERT(fixed == 1); return Item_func_length::val_int()*8; }
+ Item_func_bit_length(THD *thd, Item *a): Item_longlong_func(thd, a) {}
+ void fix_length_and_dec()
+ {
+ max_length= 11; // 0x100000000*8 = 34,359,738,368
+ }
+ longlong val_int();
const char *func_name() const { return "bit_length"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_bit_length>(thd, mem_root, this); }
};
-class Item_func_char_length :public Item_int_func
+class Item_func_char_length :public Item_long_func
{
String value;
public:
- Item_func_char_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_char_length(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "char_length"; }
void fix_length_and_dec() { max_length=10; }
@@ -1276,10 +1628,10 @@ public:
{ return get_item_copy<Item_func_char_length>(thd, mem_root, this); }
};
-class Item_func_coercibility :public Item_int_func
+class Item_func_coercibility :public Item_long_func
{
public:
- Item_func_coercibility(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_coercibility(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "coercibility"; }
void fix_length_and_dec() { max_length=10; maybe_null= 0; }
@@ -1295,29 +1647,42 @@ public:
{ return get_item_copy<Item_func_coercibility>(thd, mem_root, this); }
};
-class Item_func_locate :public Item_int_func
+
+/*
+ In the corner case LOCATE could return (4,294,967,296 + 1),
+ which would not fit into Item_long_func range.
+ But string lengths are limited with max_allowed_packet,
+ which cannot be bigger than 1024*1024*1024.
+*/
+class Item_func_locate :public Item_long_func
{
String value1,value2;
DTCollation cmp_collation;
public:
- Item_func_locate(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
- Item_func_locate(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_func_locate(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
+ Item_func_locate(THD *thd, Item *a, Item *b, Item *c)
+ :Item_long_func(thd, a, b, c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
- void fix_length_and_dec();
+ void fix_length_and_dec()
+ {
+ max_length= MY_INT32_NUM_DECIMAL_DIGITS;
+ agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ }
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); }
};
-class Item_func_field :public Item_int_func
+class Item_func_field :public Item_long_func
{
String value,tmp;
Item_result cmp_type;
DTCollation cmp_collation;
public:
- Item_func_field(THD *thd, List<Item> &list): Item_int_func(thd, list) {}
+ Item_func_field(THD *thd, List<Item> &list): Item_long_func(thd, list) {}
longlong val_int();
const char *func_name() const { return "field"; }
void fix_length_and_dec();
@@ -1326,11 +1691,11 @@ public:
};
-class Item_func_ascii :public Item_int_func
+class Item_func_ascii :public Item_long_func
{
String value;
public:
- Item_func_ascii(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_ascii(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "ascii"; }
void fix_length_and_dec() { max_length=3; }
@@ -1338,18 +1703,19 @@ public:
{ return get_item_copy<Item_func_ascii>(thd, mem_root, this); }
};
-class Item_func_ord :public Item_int_func
+class Item_func_ord :public Item_long_func
{
String value;
public:
- Item_func_ord(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_ord(THD *thd, Item *a): Item_long_func(thd, a) {}
+ void fix_length_and_dec() { fix_char_length(7); }
longlong val_int();
const char *func_name() const { return "ord"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_ord>(thd, mem_root, this); }
};
-class Item_func_find_in_set :public Item_int_func
+class Item_func_find_in_set :public Item_long_func
{
String value,value2;
uint enum_value;
@@ -1357,7 +1723,7 @@ class Item_func_find_in_set :public Item_int_func
DTCollation cmp_collation;
public:
Item_func_find_in_set(THD *thd, Item *a, Item *b):
- Item_int_func(thd, a, b), enum_value(0) {}
+ Item_long_func(thd, a, b), enum_value(0) {}
longlong val_int();
const char *func_name() const { return "find_in_set"; }
void fix_length_and_dec();
@@ -1367,11 +1733,11 @@ public:
/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */
-class Item_func_bit: public Item_int_func
+class Item_func_bit: public Item_longlong_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) {}
+ Item_func_bit(THD *thd, Item *a, Item *b): Item_longlong_func(thd, a, b) {}
+ Item_func_bit(THD *thd, Item *a): Item_longlong_func(thd, a) {}
void fix_length_and_dec() { unsigned_flag= 1; }
virtual inline void print(String *str, enum_query_type query_type)
@@ -1403,10 +1769,10 @@ public:
{ return get_item_copy<Item_func_bit_and>(thd, mem_root, this); }
};
-class Item_func_bit_count :public Item_int_func
+class Item_func_bit_count :public Item_long_func
{
public:
- Item_func_bit_count(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_bit_count(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "bit_count"; }
void fix_length_and_dec() { max_length=2; }
@@ -1453,19 +1819,18 @@ public:
};
-class Item_func_last_insert_id :public Item_int_func
+class Item_func_last_insert_id :public Item_longlong_func
{
public:
- Item_func_last_insert_id(THD *thd): Item_int_func(thd) {}
- Item_func_last_insert_id(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_last_insert_id(THD *thd): Item_longlong_func(thd) {}
+ Item_func_last_insert_id(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
void fix_length_and_dec()
{
- unsigned_flag= TRUE;
+ unsigned_flag= true;
if (arg_count)
max_length= args[0]->max_length;
- unsigned_flag=1;
}
bool fix_fields(THD *thd, Item **ref);
bool check_vcol_func_processor(void *arg)
@@ -1477,11 +1842,11 @@ public:
};
-class Item_func_benchmark :public Item_int_func
+class Item_func_benchmark :public Item_long_func
{
public:
Item_func_benchmark(THD *thd, Item *count_expr, Item *expr):
- Item_int_func(thd, count_expr, expr)
+ Item_long_func(thd, count_expr, expr)
{}
longlong val_int();
const char *func_name() const { return "benchmark"; }
@@ -1499,10 +1864,11 @@ public:
void item_func_sleep_init(void);
void item_func_sleep_free(void);
-class Item_func_sleep :public Item_int_func
+class Item_func_sleep :public Item_long_func
{
public:
- Item_func_sleep(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_sleep(THD *thd, Item *a): Item_long_func(thd, a) {}
+ void fix_length_and_dec() { fix_char_length(1); }
bool const_item() const { return 0; }
const char *func_name() const { return "sleep"; }
table_map used_tables() const
@@ -1604,7 +1970,6 @@ public:
}
}
void cleanup();
- Item_result result_type () const { return udf.result_type(); }
bool eval_not_null_tables(void *opt_arg)
{
not_null_tables_cache= 0;
@@ -1642,7 +2007,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; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_udf_float>(thd, mem_root, this); }
@@ -1660,8 +2025,7 @@ public:
longlong val_int();
double val_real() { return (double) Item_func_udf_int::val_int(); }
String *val_str(String *str);
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
void fix_length_and_dec() { decimals= 0; max_length= 21; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_udf_int>(thd, mem_root, this); }
@@ -1679,8 +2043,7 @@ public:
double val_real();
my_decimal *val_decimal(my_decimal *);
String *val_str(String *str);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_udf_decimal>(thd, mem_root, this); }
@@ -1719,8 +2082,7 @@ public:
string2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
return dec_buf;
}
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return string_field_type(); }
+ const Type_handler *type_handler() const { return string_type_handler(); }
void 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); }
@@ -1746,6 +2108,7 @@ public:
Item_int_func(thd) {}
Item_func_udf_int(THD *thd, udf_func *udf_arg, List<Item> &list):
Item_int_func(thd, list) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
};
@@ -1757,6 +2120,7 @@ public:
Item_int_func(thd) {}
Item_func_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list):
Item_int_func(thd, list) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
};
@@ -1772,7 +2136,6 @@ public:
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
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; }
};
@@ -1781,11 +2144,11 @@ public:
void mysql_ull_cleanup(THD *thd);
void mysql_ull_set_explicit_lock_duration(THD *thd);
-class Item_func_get_lock :public Item_int_func
+class Item_func_get_lock :public Item_long_func
{
String value;
public:
- Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_int_func(thd, a, b) {}
+ Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_long_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;}
@@ -1803,11 +2166,11 @@ class Item_func_get_lock :public Item_int_func
{ return get_item_copy<Item_func_get_lock>(thd, mem_root, this); }
};
-class Item_func_release_lock :public Item_int_func
+class Item_func_release_lock :public Item_long_func
{
String value;
public:
- Item_func_release_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_release_lock(THD *thd, Item *a): Item_long_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;}
@@ -1827,15 +2190,16 @@ public:
/* replication functions */
-class Item_master_pos_wait :public Item_int_func
+class Item_master_pos_wait :public Item_longlong_func
{
String value;
public:
- Item_master_pos_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_master_pos_wait(THD *thd, Item *a, Item *b)
+ :Item_longlong_func(thd, a, b) {}
Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c):
- Item_int_func(thd, a, b, c) {}
+ Item_longlong_func(thd, a, b, c) {}
Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c, Item *d):
- Item_int_func(thd, a, b, c, d) {}
+ Item_longlong_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;}
@@ -1848,12 +2212,14 @@ public:
};
-class Item_master_gtid_wait :public Item_int_func
+class Item_master_gtid_wait :public Item_long_func
{
String value;
public:
- Item_master_gtid_wait(THD *thd, Item *a): Item_int_func(thd, a) {}
- Item_master_gtid_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_master_gtid_wait(THD *thd, Item *a)
+ :Item_long_func(thd, a) {}
+ Item_master_gtid_wait(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "master_gtid_wait"; }
void fix_length_and_dec() { max_length=2; }
@@ -1879,14 +2245,18 @@ class Item_func_user_var :public Item_hybrid_func
protected:
user_var_entry *m_var_entry;
public:
- LEX_STRING name; // keep it public
- Item_func_user_var(THD *thd, LEX_STRING a)
- :Item_hybrid_func(thd), m_var_entry(NULL), name(a) { }
- Item_func_user_var(THD *thd, LEX_STRING a, Item *b)
- :Item_hybrid_func(thd, b), m_var_entry(NULL), name(a) { }
+ LEX_CSTRING name; // keep it public
+ Item_func_user_var(THD *thd, const LEX_CSTRING *a)
+ :Item_hybrid_func(thd), m_var_entry(NULL), name(*a) { }
+ Item_func_user_var(THD *thd, const LEX_CSTRING *a, Item *b)
+ :Item_hybrid_func(thd, b), m_var_entry(NULL), name(*a) { }
Item_func_user_var(THD *thd, Item_func_user_var *item)
:Item_hybrid_func(thd, item),
m_var_entry(item->m_var_entry), name(item->name) { }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return create_table_field_from_handler(table); }
+ Field *create_field_for_create_select(TABLE *table)
+ { return create_table_field_from_handler(table); }
bool check_vcol_func_processor(void *arg);
};
@@ -1917,7 +2287,7 @@ class Item_func_set_user_var :public Item_func_user_var
} save_result;
public:
- Item_func_set_user_var(THD *thd, LEX_STRING a, Item *b):
+ Item_func_set_user_var(THD *thd, const LEX_CSTRING *a, Item *b):
Item_func_user_var(thd, a, b),
entry_thread_id(0)
{}
@@ -1941,19 +2311,13 @@ public:
bool is_null_result();
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, bool unsigned_arg);
- bool send(Protocol *protocol, String *str_arg);
+ bool send(Protocol *protocol, st_value *buffer);
void make_field(THD *thd, Send_field *tmp_field);
bool check(bool use_result_field);
void save_item_result(Item *item);
bool update();
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
- Field *create_field_for_create_select(TABLE *table)
- {
- return result_type() != STRING_RESULT ?
- create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) :
- tmp_table_field_from_field_type(table, false, true);
- }
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@ -1986,10 +2350,10 @@ class Item_func_get_user_var :public Item_func_user_var,
private Settable_routine_parameter
{
public:
- Item_func_get_user_var(THD *thd, LEX_STRING a):
+ Item_func_get_user_var(THD *thd, const LEX_CSTRING *a):
Item_func_user_var(thd, a) {}
enum Functype functype() const { return GUSERVAR_FUNC; }
- LEX_STRING get_name() { return name; }
+ LEX_CSTRING get_name() { return name; }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal*);
@@ -2029,11 +2393,12 @@ public:
*/
class Item_user_var_as_out_param :public Item
{
- LEX_STRING name;
+ LEX_CSTRING name;
user_var_entry *entry;
public:
- Item_user_var_as_out_param(THD *thd, LEX_STRING a): Item(thd), name(a)
- { set_name(thd, a.str, 0, system_charset_info); }
+ Item_user_var_as_out_param(THD *thd, const LEX_CSTRING *a)
+ :Item(thd), name(*a)
+ { set_name(thd, a->str, a->length, system_charset_info); }
/* We should return something different from FIELD_ITEM here */
enum Type type() const { return STRING_ITEM;}
double val_real();
@@ -2045,7 +2410,7 @@ public:
void print_for_load(THD *thd, String *str);
void set_null_value(CHARSET_INFO* cs);
void set_value(const char *str, uint length, CHARSET_INFO* cs);
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_user_var_as_out_param>(thd, mem_root, this); }
};
@@ -2061,7 +2426,7 @@ class Item_func_get_system_var :public Item_func
{
sys_var *var;
enum_var_type var_type, orig_var_type;
- LEX_STRING component;
+ LEX_CSTRING component;
longlong cached_llval;
double cached_dval;
String cached_strval;
@@ -2072,7 +2437,7 @@ class Item_func_get_system_var :public Item_func
public:
Item_func_get_system_var(THD *thd, sys_var *var_arg,
enum_var_type var_type_arg,
- LEX_STRING *component_arg, const char *name_arg,
+ LEX_CSTRING *component_arg, const char *name_arg,
size_t name_len_arg);
enum Functype functype() const { return GSYSVAR_FUNC; }
void update_null_value();
@@ -2080,8 +2445,7 @@ public:
void print(String *str, enum_query_type query_type);
bool const_item() const { return true; }
table_map used_tables() const { return 0; }
- enum Item_result result_type() const;
- enum_field_types field_type() const;
+ const Type_handler *type_handler() const;
double val_real();
longlong val_int();
String* val_str(String*);
@@ -2208,11 +2572,11 @@ public:
{ return get_item_copy<Item_func_bit_xor>(thd, mem_root, this); }
};
-class Item_func_is_free_lock :public Item_int_func
+class Item_func_is_free_lock :public Item_long_func
{
String value;
public:
- Item_func_is_free_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_is_free_lock(THD *thd, Item *a): Item_long_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;}
@@ -2224,11 +2588,11 @@ public:
{ return get_item_copy<Item_func_is_free_lock>(thd, mem_root, this); }
};
-class Item_func_is_used_lock :public Item_int_func
+class Item_func_is_used_lock :public Item_long_func
{
String value;
public:
- Item_func_is_used_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_is_used_lock(THD *thd, Item *a): Item_long_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;}
@@ -2240,47 +2604,44 @@ public:
{ return get_item_copy<Item_func_is_used_lock>(thd, mem_root, this); }
};
-/* For type casts */
-
-enum Cast_target
-{
- ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
- ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
- ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE
-};
-
struct Lex_cast_type_st: public Lex_length_and_dec_st
{
private:
- Cast_target m_type;
+ const Type_handler *m_type_handler;
public:
- void set(Cast_target type, const char *length, const char *dec)
+ void set(const Type_handler *handler, const char *length, const char *dec)
{
- m_type= type;
+ m_type_handler= handler;
Lex_length_and_dec_st::set(length, dec);
}
- void set(Cast_target type, Lex_length_and_dec_st length_and_dec)
+ void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec)
{
- m_type= type;
+ m_type_handler= handler;
Lex_length_and_dec_st::operator=(length_and_dec);
}
- void set(Cast_target type, const char *length)
+ void set(const Type_handler *handler, const char *length)
+ {
+ set(handler, length, 0);
+ }
+ void set(const Type_handler *handler)
{
- set(type, length, 0);
+ set(handler, 0, 0);
}
- void set(Cast_target type)
+ const Type_handler *type_handler() const { return m_type_handler; }
+ Item *create_typecast_item(THD *thd, Item *item, CHARSET_INFO *cs= NULL)
{
- set(type, 0, 0);
+ return m_type_handler->
+ create_typecast_item(thd, item,
+ Type_cast_attributes(length(), dec(), cs));
}
- Cast_target type() const { return m_type; }
};
-class Item_func_row_count :public Item_int_func
+class Item_func_row_count :public Item_longlong_func
{
public:
- Item_func_row_count(THD *thd): Item_int_func(thd) {}
+ Item_func_row_count(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "row_count"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
@@ -2323,7 +2684,12 @@ private:
protected:
bool is_expensive_processor(void *arg)
{ return is_expensive(); }
-
+
+ bool check_arguments() const
+ {
+ // sp_prepare_func_item() checks that the number of columns is correct
+ return false;
+ }
public:
Item_func_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name);
@@ -2340,18 +2706,16 @@ public:
const char *func_name() const;
- enum enum_field_types field_type() const;
+ const Type_handler *type_handler() const;
Field *create_field_for_create_select(TABLE *table)
{
return result_type() != STRING_RESULT ?
sp_result_field :
- tmp_table_field_from_field_type(table, false, false);
+ tmp_table_field_from_field_type(table);
}
void make_field(THD *thd, Send_field *tmp_field);
- Item_result result_type() const;
-
longlong val_int()
{
if (execute())
@@ -2411,6 +2775,10 @@ public:
{
return sp_result_field;
}
+ const sp_name *get_sp_name() const
+ {
+ return m_name;
+ }
bool check_vcol_func_processor(void *arg);
bool limit_index_condition_pushdown_processor(void *opt_arg)
@@ -2434,10 +2802,10 @@ public:
};
-class Item_func_found_rows :public Item_int_func
+class Item_func_found_rows :public Item_longlong_func
{
public:
- Item_func_found_rows(THD *thd): Item_int_func(thd) {}
+ Item_func_found_rows(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "found_rows"; }
void fix_length_and_dec() { decimals= 0; maybe_null=0; }
@@ -2450,12 +2818,55 @@ public:
};
+class Item_func_oracle_sql_rowcount :public Item_longlong_func
+{
+public:
+ Item_func_oracle_sql_rowcount(THD *thd): Item_longlong_func(thd) {}
+ longlong val_int();
+ const char *func_name() const { return "SQL%ROWCOUNT"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
+ }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_oracle_sql_rowcount>(thd, mem_root, this); }
+};
+
+
+class Item_func_sqlcode: public Item_long_func
+{
+public:
+ Item_func_sqlcode(THD *thd): Item_long_func(thd) { }
+ longlong val_int();
+ const char *func_name() const { return "SQLCODE"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
+ }
+ void fix_length_and_dec()
+ {
+ maybe_null= null_value= false;
+ max_length= 11;
+ }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_sqlcode>(thd, mem_root, this); }
+};
+
+
void uuid_short_init();
-class Item_func_uuid_short :public Item_int_func
+class Item_func_uuid_short :public Item_longlong_func
{
public:
- Item_func_uuid_short(THD *thd): Item_int_func(thd) {}
+ Item_func_uuid_short(THD *thd): Item_longlong_func(thd) {}
const char *func_name() const { return "uuid_short"; }
longlong val_int();
void fix_length_and_dec()
@@ -2481,14 +2892,13 @@ public:
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec();
- enum Item_result result_type () const { return last_value->result_type(); }
const char *func_name() const { return "last_value"; }
+ const Type_handler *type_handler() const { return last_value->type_handler(); }
bool eval_not_null_tables(void *)
{
not_null_tables_cache= 0;
return 0;
}
- enum_field_types field_type() const { return last_value->field_type(); }
bool const_item() const { return 0; }
void evaluate_sideeffects();
void update_used_tables()
@@ -2501,11 +2911,73 @@ public:
};
-Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
- LEX_STRING component);
-extern bool check_reserved_words(LEX_STRING *name);
-extern enum_field_types agg_field_type(Item **items, uint nitems,
- bool treat_bit_as_number);
+/* Implementation for sequences: NEXT VALUE FOR sequence and NEXTVAL() */
+
+class Item_func_nextval :public Item_longlong_func
+{
+protected:
+ TABLE_LIST *table_list;
+public:
+ Item_func_nextval(THD *thd, TABLE_LIST *table):
+ Item_longlong_func(thd), table_list(table) {}
+ longlong val_int();
+ const char *func_name() const { return "nextval"; }
+ void fix_length_and_dec()
+ {
+ unsigned_flag= 0;
+ max_length= MAX_BIGINT_WIDTH;
+ maybe_null= 1; /* In case of errors */
+ }
+ bool const_item() const { return 0; }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_nextval>(thd, mem_root, this); }
+ void print(String *str, enum_query_type query_type);
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg,
+ VCOL_NON_DETERMINISTIC);
+ }
+};
+
+
+/* Implementation for sequences: LASTVAL(sequence), PostgreSQL style */
+
+class Item_func_lastval :public Item_func_nextval
+{
+public:
+ Item_func_lastval(THD *thd, TABLE_LIST *table):
+ Item_func_nextval(thd, table) {}
+ longlong val_int();
+ const char *func_name() const { return "lastval"; }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_lastval>(thd, mem_root, this); }
+};
+
+
+/* Implementation for sequences: SETVAL(sequence), PostgreSQL style */
+
+class Item_func_setval :public Item_func_nextval
+{
+ longlong nextval;
+ ulonglong round;
+ bool is_used;
+public:
+ Item_func_setval(THD *thd, TABLE_LIST *table, longlong nextval_arg,
+ ulonglong round_arg, bool is_used_arg)
+ : Item_func_nextval(thd, table),
+ nextval(nextval_arg), round(round_arg), is_used(is_used_arg)
+ {}
+ longlong val_int();
+ const char *func_name() const { return "setval"; }
+ void print(String *str, enum_query_type query_type);
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_setval>(thd, mem_root, this); }
+};
+
+
+Item *get_system_var(THD *thd, enum_var_type var_type, LEX_CSTRING name,
+ LEX_CSTRING component);
+extern bool check_reserved_words(const LEX_CSTRING *name);
Item *find_date_time_item(Item **args, uint nargs, uint col);
double my_double_round(double value, longlong dec, bool dec_unsigned,
bool truncate);
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 560d822bea7..e553af6110a 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -40,20 +40,11 @@
#include "opt_range.h"
-Field *Item_geometry_func::create_field_for_create_select(TABLE *t_arg)
-{
- Field *result;
- if ((result= new Field_geom(max_length, maybe_null, name, t_arg->s,
- get_geometry_type())))
- result->init(t_arg);
- return result;
-}
-
void Item_geometry_func::fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
- max_length= (uint32) 4294967295U;
+ max_length= (uint32) UINT_MAX32;
maybe_null= 1;
}
@@ -206,7 +197,7 @@ String *Item_func_as_wkt::val_str_ascii(String *str)
void Item_func_as_wkt::fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
- max_length=MAX_BLOB_WIDTH;
+ max_length= (uint32) UINT_MAX32;
maybe_null= 1;
}
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index abe189395ec..db720da18fd 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -39,12 +39,163 @@ public:
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();
- enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
- Field *create_field_for_create_select(TABLE *table);
+ const Type_handler *type_handler() const { return &type_handler_geometry; }
};
+
+/*
+ Functions returning REAL measurements of a single GEOMETRY argument
+*/
+class Item_real_func_args_geometry: public Item_real_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_real_func_args_geometry(THD *thd, Item *a)
+ :Item_real_func(thd, a) {}
+};
+
+
+/*
+ Functions returning INT measurements of a single GEOMETRY argument
+*/
+class Item_long_func_args_geometry: public Item_long_func
+{
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+protected:
+ String value;
+public:
+ Item_long_func_args_geometry(THD *thd, Item *a)
+ :Item_long_func(thd, a) {}
+};
+
+
+/*
+ Functions returning BOOL measurements of a single GEOMETRY argument
+*/
+class Item_bool_func_args_geometry: public Item_bool_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_bool_func_args_geometry(THD *thd, Item *a)
+ :Item_bool_func(thd, a) {}
+};
+
+
+/*
+ Functions returning ASCII string measurements of a single GEOMETRY argument
+*/
+class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a)
+ :Item_str_ascii_func(thd, a) {}
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
+ :Item_str_ascii_func(thd, a, b) {}
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c)
+ :Item_str_ascii_func(thd, a, b, c) {}
+};
+
+
+/*
+ Functions returning binary string measurements of a single GEOMETRY argument
+*/
+class Item_binary_func_args_geometry: public Item_str_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_binary_func_args_geometry(THD *thd, Item *a)
+ :Item_str_func(thd, a) {}
+};
+
+
+/*
+ Functions returning GEOMETRY measurements of a single GEOEMETRY argument
+*/
+class Item_geometry_func_args_geometry: public Item_geometry_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_geometry_func_args_geometry(THD *thd, Item *a)
+ :Item_geometry_func(thd, a) {}
+ Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b)
+ :Item_geometry_func(thd, a, b) {}
+};
+
+
+/*
+ Functions returning REAL result relationships between two GEOMETRY arguments
+*/
+class Item_real_func_args_geometry_geometry: public Item_real_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
+public:
+ Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
+ :Item_real_func(thd, a, b) {}
+};
+
+
+/*
+ Functions returning BOOL result relationships between two GEOMETRY arguments
+*/
+class Item_bool_func_args_geometry_geometry: public Item_bool_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
+public:
+ Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
+ :Item_bool_func(thd, a, b, c) {}
+};
+
+
class Item_func_geometry_from_text: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+ }
public:
Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
@@ -57,6 +208,11 @@ public:
class Item_func_geometry_from_wkb: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry) ||
+ check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+ }
public:
Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_wkb(THD *thd, Item *a, Item *srid):
@@ -71,6 +227,12 @@ public:
class Item_func_geometry_from_json: public Item_geometry_func
{
String tmp_js;
+ bool check_arguments() const
+ {
+ // TODO: check with Alexey, for better args[1] and args[2] type control
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+ }
public:
Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {}
Item_func_geometry_from_json(THD *thd, Item *js, Item *opt):
@@ -84,10 +246,11 @@ public:
};
-class Item_func_as_wkt: public Item_str_ascii_func
+class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
{
public:
- Item_func_as_wkt(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+ Item_func_as_wkt(THD *thd, Item *a)
+ :Item_str_ascii_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_astext"; }
String *val_str_ascii(String *);
void fix_length_and_dec();
@@ -95,26 +258,41 @@ public:
{ return get_item_copy<Item_func_as_wkt>(thd, mem_root, this); }
};
-class Item_func_as_wkb: public Item_geometry_func
+class Item_func_as_wkb: public Item_binary_func_args_geometry
{
public:
- Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_as_wkb(THD *thd, Item *a)
+ :Item_binary_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
- enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
+ const Type_handler *type_handler() const { return &type_handler_long_blob; }
+ void fix_length_and_dec()
+ {
+ collation.set(&my_charset_bin);
+ decimals=0;
+ max_length= (uint32) UINT_MAX32;
+ maybe_null= 1;
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); }
};
-class Item_func_as_geojson: public Item_str_ascii_func
+class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
{
+ bool check_arguments() const
+ {
+ // TODO: check with Alexey, for better args[1] and args[2] type control
+ return Item_str_ascii_func_args_geometry::check_arguments() ||
+ check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+ }
public:
- Item_func_as_geojson(THD *thd, Item *js): Item_str_ascii_func(thd, js) {}
- Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits):
- Item_str_ascii_func(thd, js, max_dec_digits) {}
- Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt):
- Item_str_ascii_func(thd, js, max_dec_digits, opt) {}
+ Item_func_as_geojson(THD *thd, Item *js)
+ :Item_str_ascii_func_args_geometry(thd, js) {}
+ Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
+ :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {}
+ Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
+ :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
const char *func_name() const { return "st_asgeojson"; }
void fix_length_and_dec();
String *val_str_ascii(String *);
@@ -123,10 +301,11 @@ public:
};
-class Item_func_geometry_type: public Item_str_ascii_func
+class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
{
public:
- Item_func_geometry_type(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+ Item_func_geometry_type(THD *thd, Item *a)
+ :Item_str_ascii_func_args_geometry(thd, a) {}
String *val_str_ascii(String *);
const char *func_name() const { return "st_geometrytype"; }
void fix_length_and_dec()
@@ -141,7 +320,7 @@ public:
// #define HEAVY_CONVEX_HULL
-class Item_func_convexhull: public Item_geometry_func
+class Item_func_convexhull: public Item_geometry_func_args_geometry
{
class ch_node: public Gcalc_dyn_list::Item
{
@@ -164,7 +343,8 @@ class Item_func_convexhull: public Item_geometry_func
ch_node *new_ch_node() { return (ch_node *) res_heap.new_item(); }
int add_node_to_line(ch_node **p_cur, int dir, const Gcalc_heap::Info *pi);
public:
- Item_func_convexhull(THD *thd, Item *a): Item_geometry_func(thd, a),
+ Item_func_convexhull(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a),
res_heap(8192, sizeof(ch_node))
{}
const char *func_name() const { return "st_convexhull"; }
@@ -174,10 +354,11 @@ public:
};
-class Item_func_centroid: public Item_geometry_func
+class Item_func_centroid: public Item_geometry_func_args_geometry
{
public:
- Item_func_centroid(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_centroid(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_centroid"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
@@ -185,10 +366,11 @@ public:
{ return get_item_copy<Item_func_centroid>(thd, mem_root, this); }
};
-class Item_func_envelope: public Item_geometry_func
+class Item_func_envelope: public Item_geometry_func_args_geometry
{
public:
- Item_func_envelope(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_envelope(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_envelope"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
@@ -197,7 +379,7 @@ public:
};
-class Item_func_boundary: public Item_geometry_func
+class Item_func_boundary: public Item_geometry_func_args_geometry
{
class Transporter : public Gcalc_shape_transporter
{
@@ -222,7 +404,8 @@ class Item_func_boundary: public Item_geometry_func
};
Gcalc_result_receiver res_receiver;
public:
- Item_func_boundary(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_boundary(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_boundary"; }
String *val_str(String *);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -232,6 +415,8 @@ public:
class Item_func_point: public Item_geometry_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_real(0, 2); }
public:
Item_func_point(THD *thd, Item *a, Item *b): Item_geometry_func(thd, a, b) {}
Item_func_point(THD *thd, Item *a, Item *b, Item *srid):
@@ -243,12 +428,12 @@ public:
{ return get_item_copy<Item_func_point>(thd, mem_root, this); }
};
-class Item_func_spatial_decomp: public Item_geometry_func
+class Item_func_spatial_decomp: public Item_geometry_func_args_geometry
{
enum Functype decomp_func;
public:
Item_func_spatial_decomp(THD *thd, Item *a, Item_func::Functype ft):
- Item_geometry_func(thd, a) { decomp_func = ft; }
+ Item_geometry_func_args_geometry(thd, a) { decomp_func = ft; }
const char *func_name() const
{
switch (decomp_func)
@@ -269,12 +454,19 @@ public:
{ return get_item_copy<Item_func_spatial_decomp>(thd, mem_root, this); }
};
-class Item_func_spatial_decomp_n: public Item_geometry_func
+class Item_func_spatial_decomp_n: public Item_geometry_func_args_geometry
{
enum Functype decomp_func_n;
+ bool check_arguments() const
+ {
+ return Item_geometry_func_args_geometry::check_arguments() ||
+ args[1]->check_type_can_return_int(func_name());
+ }
public:
- Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft):
- Item_geometry_func(thd, a, b) { decomp_func_n = ft; }
+ Item_func_spatial_decomp_n(THD *thd, Item *a, Item *b, Item_func::Functype ft)
+ :Item_geometry_func_args_geometry(thd, a, b),
+ decomp_func_n(ft)
+ { }
const char *func_name() const
{
switch (decomp_func_n)
@@ -297,6 +489,10 @@ public:
class Item_func_spatial_collection: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return check_argument_types_or_binary(&type_handler_geometry, 0, arg_count);
+ }
enum Geometry::wkbType coll_type;
enum Geometry::wkbType item_type;
public:
@@ -342,6 +538,11 @@ protected:
SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
KEY_PART *key_part,
Item_func::Functype type, Item *value);
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
public:
Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
Item_bool_func2_with_rev(thd, a, b), spatial_rel(sp_rel)
@@ -392,15 +593,20 @@ public:
};
-class Item_func_spatial_relate: public Item_bool_func
+class Item_func_spatial_relate: public Item_bool_func_args_geometry_geometry
{
Gcalc_heap collector;
Gcalc_scan_iterator scan_it;
Gcalc_function func;
String tmp_value1, tmp_value2, tmp_matrix;
+ bool check_arguments() const
+ {
+ return Item_bool_func_args_geometry_geometry::check_arguments() ||
+ args[2]->check_type_general_purpose_string(func_name());
+ }
public:
Item_func_spatial_relate(THD *thd, Item *a, Item *b, Item *matrix):
- Item_bool_func(thd, a, b, matrix)
+ Item_bool_func_args_geometry_geometry(thd, a, b, matrix)
{ }
longlong val_int();
const char *func_name() const { return "st_relate"; }
@@ -416,6 +622,11 @@ public:
class Item_func_spatial_operation: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
public:
Gcalc_function::op_type spatial_op;
Gcalc_heap collector;
@@ -441,8 +652,13 @@ public:
};
-class Item_func_buffer: public Item_geometry_func
+class Item_func_buffer: public Item_geometry_func_args_geometry
{
+ bool check_arguments() const
+ {
+ return Item_geometry_func_args_geometry::check_arguments() ||
+ args[1]->check_type_can_return_real(func_name());
+ }
protected:
class Transporter : public Gcalc_operation_transporter
{
@@ -484,8 +700,8 @@ protected:
Gcalc_operation_reducer operation;
public:
- Item_func_buffer(THD *thd, Item *obj, Item *distance):
- Item_geometry_func(thd, obj, distance) {}
+ Item_func_buffer(THD *thd, Item *obj, Item *distance)
+ :Item_geometry_func_args_geometry(thd, obj, distance) {}
const char *func_name() const { return "st_buffer"; }
String *val_str(String *);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -493,10 +709,11 @@ public:
};
-class Item_func_isempty: public Item_bool_func
+class Item_func_isempty: public Item_bool_func_args_geometry
{
public:
- Item_func_isempty(THD *thd, Item *a): Item_bool_func(thd, a) {}
+ Item_func_isempty(THD *thd, Item *a)
+ :Item_bool_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isempty"; }
void fix_length_and_dec() { maybe_null= 1; }
@@ -505,14 +722,15 @@ public:
{ return get_item_copy<Item_func_isempty>(thd, mem_root, this); }
};
-class Item_func_issimple: public Item_int_func
+class Item_func_issimple: public Item_long_func_args_geometry
{
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
String tmp;
public:
- Item_func_issimple(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_issimple(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_issimple"; }
void fix_length_and_dec() { decimals=0; max_length=2; }
@@ -521,10 +739,11 @@ public:
{ return get_item_copy<Item_func_issimple>(thd, mem_root, this); }
};
-class Item_func_isclosed: public Item_int_func
+class Item_func_isclosed: public Item_long_func_args_geometry
{
public:
- Item_func_isclosed(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_isclosed(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isclosed"; }
void fix_length_and_dec() { decimals=0; max_length=2; }
@@ -543,11 +762,11 @@ public:
{ return get_item_copy<Item_func_isring>(thd, mem_root, this); }
};
-class Item_func_dimension: public Item_int_func
+class Item_func_dimension: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_dimension(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dimension(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_dimension"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -555,11 +774,11 @@ public:
{ return get_item_copy<Item_func_dimension>(thd, mem_root, this); }
};
-class Item_func_x: public Item_real_func
+
+class Item_func_x: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_x(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_x"; }
void fix_length_and_dec()
@@ -572,11 +791,10 @@ public:
};
-class Item_func_y: public Item_real_func
+class Item_func_y: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_y(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_y"; }
void fix_length_and_dec()
@@ -589,11 +807,11 @@ public:
};
-class Item_func_numgeometries: public Item_int_func
+class Item_func_numgeometries: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numgeometries(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numgeometries(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numgeometries"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -602,11 +820,11 @@ public:
};
-class Item_func_numinteriorring: public Item_int_func
+class Item_func_numinteriorring: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numinteriorring(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numinteriorring(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numinteriorrings"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -615,11 +833,11 @@ public:
};
-class Item_func_numpoints: public Item_int_func
+class Item_func_numpoints: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numpoints(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numpoints(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numpoints"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -628,11 +846,10 @@ public:
};
-class Item_func_area: public Item_real_func
+class Item_func_area: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_area(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_area"; }
void fix_length_and_dec()
@@ -645,11 +862,12 @@ public:
};
-class Item_func_glength: public Item_real_func
+class Item_func_glength: public Item_real_func_args_geometry
{
String value;
public:
- Item_func_glength(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_glength(THD *thd, Item *a)
+ :Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_length"; }
void fix_length_and_dec()
@@ -662,11 +880,11 @@ public:
};
-class Item_func_srid: public Item_int_func
+class Item_func_srid: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_srid(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_srid(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "srid"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
@@ -675,7 +893,7 @@ public:
};
-class Item_func_distance: public Item_real_func
+class Item_func_distance: public Item_real_func_args_geometry_geometry
{
String tmp_value1;
String tmp_value2;
@@ -683,7 +901,8 @@ class Item_func_distance: public Item_real_func
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
- Item_func_distance(THD *thd, Item *a, Item *b): Item_real_func(thd, a, b) {}
+ Item_func_distance(THD *thd, Item *a, Item *b)
+ :Item_real_func_args_geometry_geometry(thd, a, b) {}
double val_real();
const char *func_name() const { return "st_distance"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -691,14 +910,15 @@ public:
};
-class Item_func_pointonsurface: public Item_geometry_func
+class Item_func_pointonsurface: public Item_geometry_func_args_geometry
{
String tmp_value;
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
public:
- Item_func_pointonsurface(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_pointonsurface(THD *thd, Item *a)
+ :Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_pointonsurface"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
@@ -708,11 +928,12 @@ public:
#ifndef DBUG_OFF
-class Item_func_gis_debug: public Item_int_func
+class Item_func_gis_debug: public Item_long_func
{
public:
- Item_func_gis_debug(THD *thd, Item *a): Item_int_func(thd, a)
+ Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
{ null_value= false; }
+ void fix_length_and_dec() { fix_char_length(10); }
const char *func_name() const { return "st_gis_debug"; }
longlong val_int();
bool check_vcol_func_processor(void *arg)
diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h
index 741b9f7d997..33586c29175 100644
--- a/sql/item_inetfunc.h
+++ b/sql/item_inetfunc.h
@@ -24,10 +24,10 @@
Item_func_inet_aton implements INET_ATON() SQL-function.
*************************************************************************/
-class Item_func_inet_aton : public Item_int_func
+class Item_func_inet_aton : public Item_longlong_func
{
public:
- Item_func_inet_aton(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_inet_aton(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "inet_aton"; }
void fix_length_and_dec()
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index c7639bc2513..9e9b26e2119 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -390,7 +390,7 @@ longlong Item_func_json_valid::val_int()
void Item_func_json_exists::fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
maybe_null= 1;
path.set_constant_flag(args[1]->const_item());
}
@@ -890,7 +890,7 @@ void Item_func_json_contains::fix_length_and_dec()
maybe_null= 1;
if (arg_count > 2)
path.set_constant_flag(args[2]->const_item());
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
}
@@ -1135,7 +1135,7 @@ void Item_func_json_contains_path::fix_length_and_dec()
ooa_parsed= FALSE;
maybe_null= 1;
mark_constant_paths(paths, args+2, arg_count-2);
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
}
@@ -1258,6 +1258,7 @@ longlong Item_func_json_contains_path::val_int()
longlong result;
json_path_t p;
int n_found;
+ LINT_INIT(n_found);
if ((null_value= args[0]->null_value))
return 0;
@@ -1985,6 +1986,7 @@ String *Item_func_json_merge::val_str(String *str)
json_engine_t je1, je2;
String *js1= args[0]->val_json(&tmp_js1), *js2;
uint n_arg;
+ LINT_INIT(js2);
if (args[0]->null_value)
goto null_return;
@@ -2048,6 +2050,7 @@ void Item_func_json_length::fix_length_and_dec()
if (arg_count > 1)
path.set_constant_flag(args[1]->const_item());
maybe_null= 1;
+ max_length= 10;
}
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index 394ed5f189a..4235bd3ea9f 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -40,27 +40,26 @@ public:
};
-class Item_func_json_valid: public Item_int_func
+class Item_func_json_valid: public Item_bool_func
{
protected:
String tmp_value;
public:
- Item_func_json_valid(THD *thd, Item *json) : Item_int_func(thd, json) {}
+ Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {}
longlong val_int();
const char *func_name() const { return "json_valid"; }
void fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ Item_bool_func::fix_length_and_dec();
maybe_null= 1;
}
- bool is_bool_type() { return true; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_valid>(thd, mem_root, this); }
};
-class Item_func_json_exists: public Item_int_func
+class Item_func_json_exists: public Item_bool_func
{
protected:
json_path_with_flags path;
@@ -68,9 +67,8 @@ protected:
public:
Item_func_json_exists(THD *thd, Item *js, Item *i_path):
- Item_int_func(thd, js, i_path) {}
+ Item_bool_func(thd, js, i_path) {}
const char *func_name() const { return "json_exists"; }
- bool is_bool_type() { return true; }
void 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); }
@@ -170,7 +168,7 @@ public:
};
-class Item_func_json_contains: public Item_int_func
+class Item_func_json_contains: public Item_bool_func
{
protected:
String tmp_js;
@@ -180,7 +178,7 @@ protected:
String tmp_val, *val;
public:
Item_func_json_contains(THD *thd, List<Item> &list):
- Item_int_func(thd, list) {}
+ Item_bool_func(thd, list) {}
const char *func_name() const { return "json_contains"; }
void fix_length_and_dec();
longlong val_int();
@@ -189,7 +187,7 @@ public:
};
-class Item_func_json_contains_path: public Item_int_func
+class Item_func_json_contains_path: public Item_bool_func
{
protected:
String tmp_js;
@@ -201,7 +199,7 @@ protected:
public:
Item_func_json_contains_path(THD *thd, List<Item> &list):
- Item_int_func(thd, list), tmp_paths(0) {}
+ Item_bool_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();
@@ -290,7 +288,7 @@ public:
};
-class Item_func_json_length: public Item_int_func
+class Item_func_json_length: public Item_long_func
{
protected:
json_path_with_flags path;
@@ -298,7 +296,7 @@ protected:
String tmp_path;
public:
Item_func_json_length(THD *thd, List<Item> &list):
- Item_int_func(thd, list) {}
+ Item_long_func(thd, list) {}
const char *func_name() const { return "json_length"; }
void fix_length_and_dec();
longlong val_int();
@@ -307,13 +305,14 @@ public:
};
-class Item_func_json_depth: public Item_int_func
+class Item_func_json_depth: public Item_long_func
{
protected:
String tmp_js;
public:
- Item_func_json_depth(THD *thd, Item *js): Item_int_func(thd, js) {}
+ Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {}
const char *func_name() const { return "json_depth"; }
+ void fix_length_and_dec() { max_length= 10; }
longlong val_int();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_depth>(thd, mem_root, this); }
diff --git a/sql/item_row.h b/sql/item_row.h
index cd58e15fe8b..9c92e19caab 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -56,6 +56,7 @@ public:
{}
enum Type type() const { return ROW_ITEM; };
+ const Type_handler *type_handler() const { return &type_handler_row; }
void illegal_method_call(const char *);
bool is_null() { return null_value; }
void make_field(THD *thd, Send_field *)
@@ -89,13 +90,6 @@ public:
List<Item> &fields, uint flags);
table_map used_tables() const { return used_tables_cache; };
bool const_item() const { return const_item_cache; };
- enum Item_result result_type() const { return ROW_RESULT; }
- Item_result cmp_type() const { return ROW_RESULT; }
- enum_field_types field_type() const
- {
- DBUG_ASSERT(0);
- return MYSQL_TYPE_DOUBLE;
- }
void update_used_tables()
{
used_tables_and_const_cache_init();
@@ -113,7 +107,7 @@ public:
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
bool eval_not_null_tables(void *opt_arg);
- uint cols() { return arg_count; }
+ uint cols() const { return arg_count; }
Item* element_index(uint i) { return args[i]; }
Item** addr(uint i) { return args + i; }
bool check_cols(uint c);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 3c2b2374f1e..4852a9cb425 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -457,7 +457,7 @@ String *Item_func_from_base64::val_str(String *str)
THD *thd= current_thd;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_BASE64_DATA, ER_THD(thd, ER_BAD_BASE64_DATA),
- end_ptr - res->ptr());
+ (int) (end_ptr - res->ptr()));
goto err;
}
@@ -554,125 +554,85 @@ String *Item_func_decode_histogram::val_str(String *str)
String *Item_func_concat::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- String *res,*res2,*use_as_buff;
+ THD *thd= current_thd;
+ String *res,*use_as_buff;
uint i;
bool is_const= 0;
null_value=0;
- if (!(res=args[0]->val_str(str)))
+ if (!(res= arg_val_str(0, str, &is_const)))
goto null;
use_as_buff= &tmp_value;
- is_const= args[0]->const_item();
for (i=1 ; i < arg_count ; i++)
{
if (res->length() == 0)
{
- if (!(res=args[i]->val_str(str)))
- goto null;
/*
CONCAT accumulates its result in the result of its the first
non-empty argument. Because of this we need is_const to be
evaluated only for it.
*/
- is_const= args[i]->const_item();
+ if (!(res= arg_val_str(i, str, &is_const)))
+ goto null;
}
else
{
+ const String *res2;
if (!(res2=args[i]->val_str(use_as_buff)))
- goto null;
+ goto null;
if (res2->length() == 0)
- continue;
- if (res->length()+res2->length() >
- current_thd->variables.max_allowed_packet)
- {
- THD *thd= current_thd;
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WARN_ALLOWED_PACKET_OVERFLOWED,
- ER_THD(thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED),
- func_name(),
- thd->variables.max_allowed_packet);
- goto null;
- }
- if (!is_const && res->alloced_length() >= res->length()+res2->length())
- { // Use old buffer
- res->append(*res2);
- }
- else if (str->alloced_length() >= res->length()+res2->length())
- {
- if (str->ptr() == res2->ptr())
- str->replace(0,0,*res);
- else
- {
- str->copy(*res);
- str->append(*res2);
- }
- res= str;
- use_as_buff= &tmp_value;
- }
- else if (res == &tmp_value)
- {
- if (res->append(*res2)) // Must be a blob
- goto null;
- }
- else if (res2 == &tmp_value)
- { // This can happend only 1 time
- if (tmp_value.replace(0,0,*res))
- goto null;
- res= &tmp_value;
- use_as_buff=str; // Put next arg here
- }
- else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
- res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
- {
- /*
- This happens really seldom:
- In this case res2 is sub string of tmp_value. We will
- now work in place in tmp_value to set it to res | res2
- */
- /* Chop the last characters in tmp_value that isn't in res2 */
- tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
- res2->length());
- /* Place res2 at start of tmp_value, remove chars before res2 */
- if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
- *res))
- goto null;
- res= &tmp_value;
- use_as_buff=str; // Put next arg here
- }
- else
- { // Two big const strings
- /*
- NOTE: We should be prudent in the initial allocation unit -- the
- size of the arguments is a function of data distribution, which
- can be any. Instead of overcommitting at the first row, we grow
- the allocated amount by the factor of 2. This ensures that no
- more than 25% of memory will be overcommitted on average.
- */
+ continue;
+ if (!(res= append_value(thd, res, is_const, str, &use_as_buff, res2)))
+ goto null;
+ is_const= 0;
+ }
+ }
+ res->set_charset(collation.collation);
+ return res;
- uint concat_len= res->length() + res2->length();
+null:
+ null_value=1;
+ return 0;
+}
- if (tmp_value.alloced_length() < concat_len)
- {
- if (tmp_value.alloced_length() == 0)
- {
- if (tmp_value.alloc(concat_len))
- goto null;
- }
- else
- {
- uint new_len = MY_MAX(tmp_value.alloced_length() * 2, concat_len);
- if (tmp_value.realloc(new_len))
- goto null;
- }
- }
+String *Item_func_concat_operator_oracle::val_str(String *str)
+{
+ THD *thd= current_thd;
+ DBUG_ASSERT(fixed == 1);
+ String *res, *use_as_buff;
+ uint i;
+ bool is_const= false;
+
+ null_value= 0;
+ // Search first non null argument
+ for (i= 0; i < arg_count; i++)
+ {
+ if ((res= arg_val_str(i, str, &is_const)))
+ break;
+ }
+ if (i == arg_count)
+ goto null;
- if (tmp_value.copy(*res) || tmp_value.append(*res2))
- goto null;
+ use_as_buff= &tmp_value;
- res= &tmp_value;
- use_as_buff=str;
- }
+ for (i++ ; i < arg_count ; i++)
+ {
+ if (res->length() == 0)
+ {
+ // See comments in Item_func_concat::val_str()
+ String *tmp;
+ if (!(tmp= arg_val_str(i, str, &is_const)))
+ continue;
+ res= tmp;
+ }
+ else
+ {
+ const String *res2;
+ if (!(res2= args[i]->val_str(use_as_buff)) || res2->length() == 0)
+ continue;
+ if (!(res= append_value(thd, res, is_const, str, &use_as_buff, res2)))
+ goto null;
is_const= 0;
}
}
@@ -680,11 +640,123 @@ String *Item_func_concat::val_str(String *str)
return res;
null:
- null_value=1;
+ null_value= true;
return 0;
}
+String *Item_func_concat::append_value(THD *thd,
+ String *res,
+ bool res_is_const,
+ String *str,
+ String **use_as_buff,
+ const String *res2)
+{
+ DBUG_ASSERT(res2->length() > 0);
+
+ if ((ulong) res->length() + (ulong) res2->length() >
+ thd->variables.max_allowed_packet)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER_THD(thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED),
+ func_name(),
+ thd->variables.max_allowed_packet);
+ return NULL;
+ }
+
+ uint32 concat_len= res->length() + res2->length();
+
+ if (!res_is_const && res->alloced_length() >= concat_len)
+ { // Use old buffer
+ return res->append(*res2) ? NULL : res;
+ }
+
+ if (str->alloced_length() >= concat_len)
+ {
+ if (str->ptr() == res2->ptr())
+ {
+ if (str->replace(0, 0, *res))
+ return NULL;
+ }
+ else
+ {
+ if (str->copy(*res) || str->append(*res2))
+ return NULL;
+ }
+ *use_as_buff= &tmp_value;
+ return str;
+ }
+
+ if (res == &tmp_value)
+ {
+ if (res->append(*res2)) // Must be a blob
+ return NULL;
+ return res;
+ }
+
+ if (res2 == &tmp_value)
+ { // This can happend only 1 time
+ if (tmp_value.replace(0, 0, *res))
+ return NULL;
+ *use_as_buff= str; // Put next arg here
+ return &tmp_value;
+ }
+
+ if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
+ res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
+ {
+ /*
+ This happens really seldom:
+ In this case res2 is sub string of tmp_value. We will
+ now work in place in tmp_value to set it to res | res2
+ */
+ /* Chop the last characters in tmp_value that isn't in res2 */
+ tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) +
+ res2->length());
+ /* Place res2 at start of tmp_value, remove chars before res2 */
+ if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()),
+ *res))
+ return NULL;
+ *use_as_buff= str; // Put next arg here
+ return &tmp_value;
+ }
+
+ /*
+ Two big const strings
+ NOTE: We should be prudent in the initial allocation unit -- the
+ size of the arguments is a function of data distribution, which
+ can be any. Instead of overcommitting at the first row, we grow
+ the allocated amount by the factor of 2. This ensures that no
+ more than 25% of memory will be overcommitted on average.
+ */
+
+ if (tmp_value.alloced_length() < concat_len)
+ {
+ if (tmp_value.alloced_length() == 0)
+ {
+ if (tmp_value.alloc(concat_len))
+ return NULL;
+ }
+ else
+ {
+ uint32 new_len= tmp_value.alloced_length() > INT_MAX32 ?
+ UINT_MAX32 - 1 :
+ tmp_value.alloced_length() * 2;
+ set_if_bigger(new_len, concat_len);
+ if (tmp_value.realloc(new_len))
+ return NULL;
+ }
+ }
+
+ if (tmp_value.copy(*res) || tmp_value.append(*res2))
+ return NULL;
+
+ *use_as_buff= str;
+ return &tmp_value;
+}
+
+
void Item_func_concat::fix_length_and_dec()
{
ulonglong char_length= 0;
@@ -2298,6 +2370,25 @@ String *Item_func_database::val_str(String *str)
}
+String *Item_func_sqlerrm::val_str(String *str)
+{
+ DBUG_ASSERT(fixed);
+ DBUG_ASSERT(!null_value);
+ Diagnostics_area::Sql_condition_iterator it=
+ current_thd->get_stmt_da()->sql_conditions();
+ const Sql_condition *err;
+ if ((err= it++))
+ {
+ str->copy(err->get_message_text(), err->get_message_octet_length(),
+ system_charset_info);
+ return str;
+ }
+ str->copy(C_STRING_WITH_LEN("normal, successful completition"),
+ system_charset_info);
+ return str;
+}
+
+
/**
@note USER() is replicated correctly if binlog_format=ROW or (as of
BUG#28086) binlog_format=MIXED, but is incorrectly replicated to ''
@@ -2843,29 +2934,51 @@ String *Item_func_char::val_str(String *str)
{
int32 num=(int32) args[i]->val_int();
if (!args[i]->null_value)
- {
- char tmp[4];
- if (num & 0xFF000000L)
- {
- mi_int4store(tmp, num);
- str->append(tmp, 4, &my_charset_bin);
- }
- else if (num & 0xFF0000L)
- {
- mi_int3store(tmp, num);
- str->append(tmp, 3, &my_charset_bin);
- }
- else if (num & 0xFF00L)
- {
- mi_int2store(tmp, num);
- str->append(tmp, 2, &my_charset_bin);
- }
- else
- {
- tmp[0]= (char) num;
- str->append(tmp, 1, &my_charset_bin);
- }
- }
+ append_char(str, num);
+ }
+ str->realloc(str->length()); // Add end 0 (for Purify)
+ return check_well_formed_result(str);
+}
+
+
+void Item_func_char::append_char(String *str, int32 num)
+{
+ char tmp[4];
+ if (num & 0xFF000000L)
+ {
+ mi_int4store(tmp, num);
+ str->append(tmp, 4, &my_charset_bin);
+ }
+ else if (num & 0xFF0000L)
+ {
+ mi_int3store(tmp, num);
+ str->append(tmp, 3, &my_charset_bin);
+ }
+ else if (num & 0xFF00L)
+ {
+ mi_int2store(tmp, num);
+ str->append(tmp, 2, &my_charset_bin);
+ }
+ else
+ {
+ tmp[0]= (char) num;
+ str->append(tmp, 1, &my_charset_bin);
+ }
+}
+
+
+String *Item_func_chr::val_str(String *str)
+{
+ DBUG_ASSERT(fixed == 1);
+ str->length(0);
+ str->set_charset(collation.collation);
+ int32 num=(int32) args[0]->val_int();
+ if (!args[0]->null_value)
+ append_char(str, num);
+ else
+ {
+ null_value= 1;
+ return 0;
}
str->realloc(str->length()); // Add end 0 (for Purify)
return check_well_formed_result(str);
@@ -3090,11 +3203,23 @@ err:
}
-void Item_func_rpad::fix_length_and_dec()
+void Item_func_pad::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;
+ if (arg_count == 3)
+ {
+ // Handle character set for args[0] and args[2].
+ if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2))
+ return;
+ }
+ else
+ {
+ if (agg_arg_charsets_for_string_result(collation, &args[0], 1, 1))
+ return;
+ pad_str.set_charset(collation.collation);
+ pad_str.length(0);
+ pad_str.append(" ", 1);
+ }
+
if (args[1]->const_item())
{
ulonglong char_length= (ulonglong) args[1]->val_int();
@@ -3125,11 +3250,15 @@ String *Item_func_rpad::val_str(String *str)
longlong count= args[1]->val_int();
longlong byte_count;
String *res= args[0]->val_str(str);
- String *rpad= args[2]->val_str(&rpad_str);
+ String *rpad= arg_count == 2 ? &pad_str : args[2]->val_str(&pad_str);
if (!res || args[1]->null_value || !rpad ||
((count < 0) && !args[1]->unsigned_flag))
goto err;
+
+ if (count == 0)
+ return make_empty_result();
+
null_value=0;
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Set here so that rest of code sees out-of-bound value as such. */
@@ -3154,7 +3283,6 @@ String *Item_func_rpad::val_str(String *str)
res->length(res->charpos((int) count)); // Shorten result if longer
return (res);
}
- pad_char_length= rpad->numchars();
byte_count= count * collation.collation->mbmaxlen;
{
@@ -3168,8 +3296,15 @@ String *Item_func_rpad::val_str(String *str)
goto err;
}
}
- if (args[2]->null_value || !pad_char_length)
- goto err;
+
+ if (arg_count == 3)
+ {
+ if (args[2]->null_value || !(pad_char_length= rpad->numchars()))
+ goto err;
+ }
+ else
+ pad_char_length= 1; // Implicit space
+
res_byte_length= res->length(); /* Must be done before alloc_buffer */
if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count)))
goto err;
@@ -3198,32 +3333,6 @@ String *Item_func_rpad::val_str(String *str)
}
-void 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;
-
- if (args[1]->const_item())
- {
- ulonglong char_length= (ulonglong) args[1]->val_int();
- DBUG_ASSERT(collation.collation->mbmaxlen > 0);
- /* Assumes that the maximum length of a String is < INT_MAX32. */
- /* Set here so that rest of code sees out-of-bound value as such. */
- if (args[1]->null_value)
- char_length= 0;
- else if (char_length > INT_MAX32)
- char_length= INT_MAX32;
- fix_char_length_ulonglong(char_length);
- }
- else
- {
- max_length= MAX_BLOB_WIDTH;
- maybe_null= 1;
- }
-}
-
-
String *Item_func_lpad::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -3232,11 +3341,15 @@ String *Item_func_lpad::val_str(String *str)
longlong count= args[1]->val_int();
longlong byte_count;
String *res= args[0]->val_str(&tmp_value);
- String *pad= args[2]->val_str(&lpad_str);
+ String *pad= arg_count == 2 ? &pad_str : args[2]->val_str(&pad_str);
if (!res || args[1]->null_value || !pad ||
((count < 0) && !args[1]->unsigned_flag))
goto err;
+
+ if (count == 0)
+ return make_empty_result();
+
null_value=0;
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Set here so that rest of code sees out-of-bound value as such. */
@@ -3265,7 +3378,6 @@ String *Item_func_lpad::val_str(String *str)
return res;
}
- pad_char_length= pad->numchars();
byte_count= count * collation.collation->mbmaxlen;
{
@@ -3280,9 +3392,16 @@ String *Item_func_lpad::val_str(String *str)
}
}
- if (args[2]->null_value || !pad_char_length ||
- str->alloc((uint32) byte_count))
+ if (str->alloc((uint32) byte_count))
goto err;
+
+ if (arg_count == 3)
+ {
+ if (args[2]->null_value || !(pad_char_length= pad->numchars()))
+ goto err;
+ }
+ else
+ pad_char_length= 1; // Implicit space
str->length(0);
str->set_charset(collation.collation);
@@ -3594,53 +3713,41 @@ void Item_func_weight_string::print(String *str, enum_query_type query_type)
}
-String *Item_func_hex::val_str_ascii(String *str)
+String *Item_func_hex::val_str_ascii_from_val_real(String *str)
{
- String *res;
- DBUG_ASSERT(fixed == 1);
- if (args[0]->result_type() != STRING_RESULT)
- {
- ulonglong dec;
- char ans[65],*ptr;
- /* Return hex of unsigned longlong value */
- if (args[0]->result_type() == REAL_RESULT ||
- args[0]->result_type() == DECIMAL_RESULT)
- {
- double val= args[0]->val_real();
- if ((val <= (double) LONGLONG_MIN) ||
- (val >= (double) (ulonglong) ULONGLONG_MAX))
- dec= ~(longlong) 0;
- else
- dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
- }
- else
- dec= (ulonglong) args[0]->val_int();
+ ulonglong dec;
+ double val= args[0]->val_real();
+ if ((null_value= args[0]->null_value))
+ return 0;
+ if ((val <= (double) LONGLONG_MIN) ||
+ (val >= (double) (ulonglong) ULONGLONG_MAX))
+ dec= ~(longlong) 0;
+ else
+ dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5));
+ return str->set_hex(dec) ? make_empty_result() : str;
+}
- if ((null_value= args[0]->null_value))
- return 0;
-
- if (!(ptr= longlong2str(dec, ans, 16)) ||
- str->copy(ans,(uint32) (ptr - ans),
- &my_charset_numeric))
- return make_empty_result(); // End of memory
- return str;
- }
- /* Convert given string to a hex string, character by character */
- res= args[0]->val_str(&tmp_value);
- if (!res || str->alloc(res->length()*2+1))
- {
- null_value=1;
- return 0;
- }
- null_value=0;
- str->length(res->length()*2);
- str->set_charset(&my_charset_latin1);
+String *Item_func_hex::val_str_ascii_from_val_str(String *str)
+{
+ DBUG_ASSERT(&tmp_value != str);
+ String *res= args[0]->val_str(&tmp_value);
+ DBUG_ASSERT(res != str);
+ if ((null_value= (res == NULL)))
+ return NULL;
+ return str->set_hex(res->ptr(), res->length()) ? make_empty_result() : str;
+}
- octet2hex((char*) str->ptr(), res->ptr(), res->length());
- return str;
+
+String *Item_func_hex::val_str_ascii_from_val_int(String *str)
+{
+ ulonglong dec= (ulonglong) args[0]->val_int();
+ if ((null_value= args[0]->null_value))
+ return 0;
+ return str->set_hex(dec) ? make_empty_result() : str;
}
+
/** Convert given hex string to a binary string. */
String *Item_func_unhex::val_str(String *str)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 0729f8f9c15..ab2d183dbe5 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -64,8 +64,7 @@ public:
longlong val_int();
double val_real();
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return string_field_type(); }
+ const Type_handler *type_handler() const { return string_type_handler(); }
void left_right_max_length();
bool fix_fields(THD *thd, Item **ref);
void update_null_value()
@@ -244,7 +243,40 @@ public:
class Item_func_concat :public Item_str_func
{
+protected:
String tmp_value;
+ /*
+ Get the i-th argument val_str() and its const_item()
+ @param i[IN] - The argument number
+ @param str[IN] - The buffer for val_str()
+ @param is_const[IN/OUT] - If args[i]->val_str() returned a non-null value,
+ then args[i]->const_item() is returned here.
+ Otherwise, the value of is_const is not touched.
+ @retval - the result of val_str().
+ */
+ String *arg_val_str(uint i, String *str, bool *is_const)
+ {
+ String *res= args[i]->val_str(str);
+ if (res)
+ *is_const= args[i]->const_item();
+ return res;
+ }
+ /*
+ Append a non-NULL value to the result.
+ @param [IN] thd - The current thread.
+ @param [IN/OUT] res - The current val_str() return value.
+ @param [IN] res_is_const - If "false", then OK to append to "res"
+ @param [IN/OUT] str - The val_str() argument.
+ @param [IN] res2 - The value to be appended.
+ @param [IN/OUT] use_as_buff - Which buffer to use for the next argument:
+ args[next_arg]->val_str(use_as_buff)
+ */
+ String *append_value(THD *thd,
+ String *res,
+ bool res_is_const,
+ String *str,
+ String **use_as_buff,
+ const String *res2);
public:
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) {}
@@ -255,6 +287,29 @@ public:
{ return get_item_copy<Item_func_concat>(thd, mem_root, this); }
};
+
+/*
+ This class handles the || operator in sql_mode=ORACLE.
+ Unlike the traditional MariaDB concat(), it treats NULL arguments as ''.
+*/
+class Item_func_concat_operator_oracle :public Item_func_concat
+{
+public:
+ Item_func_concat_operator_oracle(THD *thd, List<Item> &list)
+ :Item_func_concat(thd, list)
+ { }
+ Item_func_concat_operator_oracle(THD *thd, Item *a, Item *b)
+ :Item_func_concat(thd, a, b)
+ { }
+ String *val_str(String *);
+ const char *func_name() const { return "concat_operator_oracle"; }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ {
+ return get_item_copy<Item_func_concat_operator_oracle>(thd, mem_root, this);
+ }
+};
+
+
class Item_func_decode_histogram :public Item_str_func
{
public:
@@ -715,6 +770,27 @@ public:
};
+class Item_func_sqlerrm :public Item_func_sysconst
+{
+public:
+ Item_func_sqlerrm(THD *thd): Item_func_sysconst(thd) {}
+ String *val_str(String *);
+ const char *func_name() const { return "SQLERRM"; }
+ const char *fully_qualified_func_name() const { return "SQLERRM"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ }
+ void fix_length_and_dec()
+ {
+ max_length= 512 * system_charset_info->mbmaxlen;
+ null_value= maybe_null= false;
+ }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_sqlerrm>(thd, mem_root, this); }
+};
+
+
class Item_func_user :public Item_func_sysconst
{
protected:
@@ -865,7 +941,11 @@ public:
Item_func_char(THD *thd, List<Item> &list, CHARSET_INFO *cs):
Item_str_func(thd, list)
{ collation.set(cs); }
+ Item_func_char(THD *thd, Item *arg1, CHARSET_INFO *cs):
+ Item_str_func(thd, arg1)
+ { collation.set(cs); }
String *val_str(String *);
+ void append_char(String * str, int32 num);
void fix_length_and_dec()
{
max_length= arg_count * 4;
@@ -875,6 +955,20 @@ public:
{ return get_item_copy<Item_func_char>(thd, mem_root, this); }
};
+class Item_func_chr :public Item_func_char
+{
+public:
+ Item_func_chr(THD *thd, Item *arg1, CHARSET_INFO *cs):
+ Item_func_char(thd, arg1, cs) {}
+ String *val_str(String *);
+ void fix_length_and_dec()
+ {
+ max_length= 4;
+ }
+ const char *func_name() const { return "chr"; }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_chr>(thd, mem_root, this); }
+};
class Item_func_repeat :public Item_str_func
{
@@ -920,28 +1014,41 @@ public:
};
-class Item_func_rpad :public Item_str_func
+class Item_func_pad: public Item_str_func
{
- String tmp_value, rpad_str;
+protected:
+ String tmp_value, pad_str;
public:
- Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+ Item_func_pad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
Item_str_func(thd, arg1, arg2, arg3) {}
- String *val_str(String *);
+ Item_func_pad(THD *thd, Item *arg1, Item *arg2):
+ Item_str_func(thd, arg1, arg2) {}
void fix_length_and_dec();
+};
+
+
+class Item_func_rpad :public Item_func_pad
+{
+public:
+ Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+ Item_func_pad(thd, arg1, arg2, arg3) {}
+ Item_func_rpad(THD *thd, Item *arg1, Item *arg2):
+ Item_func_pad(thd, arg1, arg2) {}
+ String *val_str(String *);
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); }
};
-class Item_func_lpad :public Item_str_func
+class Item_func_lpad :public Item_func_pad
{
- String tmp_value, lpad_str;
public:
Item_func_lpad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
- Item_str_func(thd, arg1, arg2, arg3) {}
+ Item_func_pad(thd, arg1, arg2, arg3) {}
+ Item_func_lpad(THD *thd, Item *arg1, Item *arg2):
+ Item_func_pad(thd, arg1, arg2) {}
String *val_str(String *);
- void 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); }
@@ -968,17 +1075,33 @@ public:
class Item_func_hex :public Item_str_ascii_checksum_func
{
+protected:
String tmp_value;
+ /*
+ Calling arg[0]->type_handler() can be expensive on every row.
+ It's a virtual method, and in case if args[0] is a complex Item,
+ its type_handler() can call more virtual methods.
+ So let's cache it during fix_length_and_dec().
+ */
+ const Type_handler *m_arg0_type_handler;
public:
Item_func_hex(THD *thd, Item *a):
- Item_str_ascii_checksum_func(thd, a) {}
+ Item_str_ascii_checksum_func(thd, a), m_arg0_type_handler(NULL) {}
const char *func_name() const { return "hex"; }
- String *val_str_ascii(String *);
+ String *val_str_ascii_from_val_int(String *str);
+ String *val_str_ascii_from_val_real(String *str);
+ String *val_str_ascii_from_val_str(String *str);
+ String *val_str_ascii(String *str)
+ {
+ DBUG_ASSERT(fixed);
+ return m_arg0_type_handler->Item_func_hex_val_str_ascii(this, str);
+ }
void fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
decimals=0;
fix_char_length(args[0]->max_length * 2);
+ m_arg0_type_handler= args[0]->type_handler();
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_hex>(thd, mem_root, this); }
@@ -1315,11 +1438,11 @@ public:
{ return get_item_copy<Item_func_weight_string>(thd, mem_root, this); }
};
-class Item_func_crc32 :public Item_int_func
+class Item_func_crc32 :public Item_long_func
{
String value;
public:
- Item_func_crc32(THD *thd, Item *a): Item_int_func(thd, a)
+ Item_func_crc32(THD *thd, Item *a): Item_long_func(thd, a)
{ unsigned_flag= 1; }
const char *func_name() const { return "crc32"; }
void fix_length_and_dec() { max_length=10; }
@@ -1328,11 +1451,11 @@ public:
{ return get_item_copy<Item_func_crc32>(thd, mem_root, this); }
};
-class Item_func_uncompressed_length : public Item_int_func
+class Item_func_uncompressed_length : public Item_long_func
{
String value;
public:
- Item_func_uncompressed_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_uncompressed_length(THD *thd, Item *a): Item_long_func(thd, a) {}
const char *func_name() const{return "uncompressed_length";}
void fix_length_and_dec() { max_length=10; maybe_null= true; }
longlong val_int();
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4713129c49e..36ce86fca29 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -45,7 +45,7 @@
double get_post_group_estimate(JOIN* join, double join_op_rows);
-const char *exists_outer_expr_name= "<exists outer expr>";
+LEX_CSTRING exists_outer_expr_name= { STRING_WITH_LEN("<exists outer expr>") };
int check_and_do_in_subquery_rewrites(JOIN *join);
@@ -118,7 +118,7 @@ void Item_subselect::init(st_select_lex *select_lex,
*/
parsing_place= (outer_select->in_sum_expr ? NO_MATTER
: outer_select->parsing_place);
- if (unit->is_union())
+ if (unit->is_unit_op())
engine= new subselect_union_engine(unit, result, this);
else
engine= new subselect_single_select_engine(select_lex, result, this);
@@ -290,7 +290,6 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
(*ref)= substitution;
substitution->name= name;
- substitution->name_length= name_length;
if (have_to_be_excluded)
engine->exclude();
substitution= 0;
@@ -1065,7 +1064,7 @@ void Item_maxmin_subselect::no_rows_in_result()
*/
if (parsing_place != SELECT_LIST || const_item())
return;
- value= Item_cache::get_cache(thd, new (thd->mem_root) Item_null(thd));
+ value= (new (thd->mem_root) Item_null(thd))->get_cache(thd);
null_value= 0;
was_values= 0;
make_const();
@@ -1083,7 +1082,7 @@ void Item_singlerow_subselect::no_rows_in_result()
*/
if (parsing_place != SELECT_LIST || const_item())
return;
- value= Item_cache::get_cache(thd, new (thd->mem_root) Item_null(thd));
+ value= (new (thd->mem_root) Item_null(thd))->get_cache(thd);
reset();
make_const();
}
@@ -1125,7 +1124,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
SELECT_LEX *select_lex= join->select_lex;
Query_arena *arena= thd->stmt_arena;
- if (!select_lex->master_unit()->is_union() &&
+ if (!select_lex->master_unit()->is_unit_op() &&
!select_lex->table_list.elements &&
select_lex->item_list.elements == 1 &&
!select_lex->item_list.head()->with_sum_func &&
@@ -1172,23 +1171,9 @@ void Item_singlerow_subselect::store(uint i, Item *item)
row[i]->cache_value();
}
-enum Item_result Item_singlerow_subselect::result_type() const
+const Type_handler *Item_singlerow_subselect::type_handler() const
{
- return engine->type();
-}
-
-enum Item_result Item_singlerow_subselect::cmp_type() const
-{
- return engine->cmptype();
-}
-
-/*
- Don't rely on the result type to calculate field type.
- Ask the engine instead.
-*/
-enum_field_types Item_singlerow_subselect::field_type() const
-{
- return engine->field_type();
+ return engine->type_handler();
}
void Item_singlerow_subselect::fix_length_and_dec()
@@ -1259,7 +1244,7 @@ Item* Item_singlerow_subselect::expr_cache_insert_transformer(THD *tmp_thd,
}
-uint Item_singlerow_subselect::cols()
+uint Item_singlerow_subselect::cols() const
{
return engine->cols();
}
@@ -1817,7 +1802,7 @@ Item_in_subselect::single_value_transformer(JOIN *join)
if (!(join_having || select_lex->with_sum_func ||
select_lex->group_list.elements) &&
select_lex->table_list.elements == 0 &&
- !select_lex->master_unit()->is_union())
+ !select_lex->master_unit()->is_unit_op())
{
Item *where_item= (Item*) select_lex->item_list.head();
/*
@@ -1877,8 +1862,8 @@ Item_in_subselect::single_value_transformer(JOIN *join)
*/
expr= new (thd->mem_root) Item_direct_ref(thd, &select_lex->context,
(Item**)optimizer->get_cache(),
- (char *)"<no matter>",
- (char *)in_left_expr_name);
+ "<no matter>",
+ &in_left_expr_name);
}
DBUG_RETURN(false);
@@ -2101,6 +2086,8 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
if (join_having || select_lex->with_sum_func ||
select_lex->group_list.elements)
{
+ const char *tmp= this->full_name();
+ LEX_CSTRING field_name= {tmp, safe_strlen(tmp)};
Item *item= func->create(thd, expr,
new (thd->mem_root) Item_ref_null_helper(
thd,
@@ -2109,7 +2096,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
&select_lex->
ref_pointer_array[0],
(char *)"<ref>",
- this->full_name()));
+ &field_name));
if (!abort_on_null && left_expr->maybe_null)
{
/*
@@ -2121,7 +2108,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
}
if (!join_having)
- item->name= (char*) in_having_cond;
+ item->name= in_having_cond;
if (fix_having(item, select_lex))
DBUG_RETURN(true);
*having_item= item;
@@ -2146,7 +2133,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
get_cond_guard(0))))
DBUG_RETURN(true);
}
- having->name= (char*) in_having_cond;
+ having->name= in_having_cond;
if (fix_having(having, select_lex))
DBUG_RETURN(true);
*having_item= having;
@@ -2171,15 +2158,16 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
single_value_transformer but there is no corresponding action in
row_value_transformer?
*/
- item->name= (char *) in_additional_cond;
+ item->name= in_additional_cond;
if (!item->fixed && item->fix_fields(thd, 0))
DBUG_RETURN(true);
*where_item= item;
}
else
{
- if (select_lex->master_unit()->is_union())
+ if (select_lex->master_unit()->is_unit_op())
{
+ LEX_CSTRING field_name= {STRING_WITH_LEN("<result>") };
Item *new_having=
func->create(thd, expr,
new (thd->mem_root) Item_ref_null_helper(thd,
@@ -2187,7 +2175,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
this,
&select_lex->ref_pointer_array[0],
(char *)"<no matter>",
- (char *)"<result>"));
+ &field_name));
if (!abort_on_null && left_expr->maybe_null)
{
disable_cond_guard_for_const_null_left_expr(0);
@@ -2196,7 +2184,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
DBUG_RETURN(true);
}
- new_having->name= (char*) in_having_cond;
+ new_having->name= in_having_cond;
if (fix_having(new_having, select_lex))
DBUG_RETURN(true);
*having_item= new_having;
@@ -2343,7 +2331,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
bool is_having_used= (join_having || select_lex->with_sum_func ||
select_lex->group_list.first ||
!select_lex->table_list.elements);
-
+ LEX_CSTRING list_ref= { STRING_WITH_LEN("<list ref>")};
DBUG_ENTER("Item_in_subselect::create_row_in_to_exists_cond");
DBUG_ASSERT(thd == join->thd);
@@ -2365,6 +2353,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
if (select_lex->ref_pointer_array[i]->
check_cols(left_expr->element_index(i)->cols()))
DBUG_RETURN(true);
+
Item *item_eq=
new (thd->mem_root)
Item_func_eq(thd, new (thd->mem_root)
@@ -2372,12 +2361,12 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
(*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
- (char *)in_left_expr_name),
+ &in_left_expr_name),
new (thd->mem_root)
Item_ref(thd, &select_lex->context,
&select_lex->ref_pointer_array[i],
(char *)"<no matter>",
- (char *)"<list ref>"));
+ &list_ref));
Item *item_isnull=
new (thd->mem_root)
Item_func_isnull(thd,
@@ -2385,7 +2374,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
Item_ref(thd, &select_lex->context,
&select_lex->ref_pointer_array[i],
(char *)"<no matter>",
- (char *)"<list ref>"));
+ &list_ref));
Item *col_item= new (thd->mem_root)
Item_cond_or(thd, item_eq, item_isnull);
if (!abort_on_null && left_expr->element_index(i)->maybe_null &&
@@ -2406,7 +2395,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
&select_lex->
ref_pointer_array[i],
(char *)"<no matter>",
- (char *)"<list ref>"));
+ &list_ref));
if (!abort_on_null && left_expr->element_index(i)->maybe_null &&
get_cond_guard(i) )
{
@@ -2441,13 +2430,13 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
(*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
- (char *)in_left_expr_name),
+ &in_left_expr_name),
new (thd->mem_root)
Item_direct_ref(thd, &select_lex->context,
&select_lex->
ref_pointer_array[i],
(char *)"<no matter>",
- (char *)"<list ref>"));
+ &list_ref));
if (!abort_on_null && select_lex->ref_pointer_array[i]->maybe_null)
{
Item *having_col_item=
@@ -2457,8 +2446,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
Item_ref(thd, &select_lex->context,
&select_lex->ref_pointer_array[i],
(char *)"<no matter>",
- (char *)"<list ref>"));
-
+ &list_ref));
item_isnull= new (thd->mem_root)
Item_func_isnull(thd,
@@ -2467,7 +2455,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
&select_lex->
ref_pointer_array[i],
(char *)"<no matter>",
- (char *)"<list ref>"));
+ &list_ref));
item= new (thd->mem_root) Item_cond_or(thd, item, item_isnull);
if (left_expr->element_index(i)->maybe_null && get_cond_guard(i))
{
@@ -2502,7 +2490,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
if (*having_item)
{
if (!join_having)
- (*having_item)->name= (char*) in_having_cond;
+ (*having_item)->name= in_having_cond;
if (fix_having(*having_item, select_lex))
DBUG_RETURN(true);
(*having_item)->top_level_item();
@@ -2999,7 +2987,7 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
Item_direct_ref(thd, &first_select->context,
(Item**)optimizer->get_cache(),
(char *)"<no matter>",
- (char *)in_left_expr_name);
+ &in_left_expr_name);
if (in_subs->fix_fields(thd, optimizer->arguments() + 1))
{
res= TRUE;
@@ -3070,7 +3058,7 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
&unit->outer_select()->context,
optimizer->arguments(),
(char *)"<no matter>",
- (char *)exists_outer_expr_name)),
+ &exists_outer_expr_name)),
optimizer) :
(Item *)optimizer);
}
@@ -3094,7 +3082,7 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
&unit->outer_select()->context,
optimizer->arguments()[0]->addr(i),
(char *)"<no matter>",
- (char *)exists_outer_expr_name)),
+ &exists_outer_expr_name)),
thd->mem_root);
}
}
@@ -3283,7 +3271,7 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
{
outer_cols_num= left_expr->cols();
- if (unit->is_union())
+ if (unit->is_unit_op())
inner_cols= &(unit->types);
else
inner_cols= &(unit->first_select()->item_list);
@@ -3703,24 +3691,21 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
Item *sel_item;
List_iterator_fast<Item> li(item_list);
- cmp_type= res_type= STRING_RESULT;
- res_field_type= MYSQL_TYPE_VAR_STRING;
+ set_handler(&type_handler_varchar);
for (uint i= 0; (sel_item= li++); i++)
{
item->max_length= sel_item->max_length;
- res_type= sel_item->result_type();
- cmp_type= sel_item->cmp_type();
- res_field_type= sel_item->field_type();
+ set_handler(sel_item->type_handler());
item->decimals= sel_item->decimals;
item->unsigned_flag= sel_item->unsigned_flag;
maybe_null= sel_item->maybe_null;
- if (!(row[i]= Item_cache::get_cache(thd, sel_item, sel_item->cmp_type())))
+ if (!(row[i]= sel_item->get_cache(thd)))
return;
row[i]->setup(thd, sel_item);
//psergey-backport-timours: row[i]->store(sel_item);
}
if (item_list.elements > 1)
- cmp_type= res_type= ROW_RESULT;
+ set_handler(&type_handler_row);
}
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
@@ -4283,7 +4268,7 @@ int subselect_indexsubquery_engine::exec()
}
-uint subselect_single_select_engine::cols()
+uint subselect_single_select_engine::cols() const
{
//psergey-sj-backport: the following assert was gone in 6.0:
//DBUG_ASSERT(select_lex->join != 0); // should be called after fix_fields()
@@ -4292,7 +4277,7 @@ uint subselect_single_select_engine::cols()
}
-uint subselect_union_engine::cols()
+uint subselect_union_engine::cols() const
{
DBUG_ASSERT(unit->is_prepared()); // should be called after fix_fields()
return unit->types.elements;
@@ -4373,7 +4358,7 @@ void subselect_union_engine::print(String *str, enum_query_type query_type)
void subselect_uniquesubquery_engine::print(String *str,
enum_query_type query_type)
{
- char *table_name= tab->table->s->table_name.str;
+ const char *table_name= tab->table->s->table_name.str;
str->append(STRING_WITH_LEN("<primary_index_lookup>("));
tab->ref.items[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" in "));
@@ -4892,7 +4877,7 @@ my_bitmap_init_memroot(MY_BITMAP *map, uint n_bits, MEM_ROOT *mem_root)
bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
{
THD *thd= get_thd();
- select_union *result_sink;
+ select_unit *result_sink;
/* Options to create_tmp_table. */
ulonglong tmp_create_options= thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS;
/* | TMP_TABLE_FORCE_MYISAM; TIMOUR: force MYISAM */
@@ -4930,7 +4915,7 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
DBUG_RETURN(TRUE);
char buf[32];
- uint len= my_snprintf(buf, sizeof(buf), "<subquery%d>", subquery_id);
+ uint len= my_snprintf(buf, sizeof(buf), "<subquery%u>", subquery_id);
char *name;
if (!(name= (char*)thd->alloc(len + 1)))
DBUG_RETURN(TRUE);
@@ -4944,7 +4929,7 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
}
if (result_sink->create_result_table(thd, tmp_columns, TRUE,
tmp_create_options,
- name, TRUE, TRUE))
+ name, TRUE, TRUE, FALSE, 0))
DBUG_RETURN(TRUE);
tmp_table= result_sink->table;
@@ -5973,10 +5958,10 @@ void Ordered_key::print(String *str)
str->append(", (");
for (i= 0; i < key_column_count - 1; i++)
{
- str->append(key_columns[i]->field->field_name);
+ str->append(&key_columns[i]->field->field_name);
str->append(", ");
}
- str->append(key_columns[i]->field->field_name);
+ str->append(&key_columns[i]->field->field_name);
str->append("), ");
str->append("null_bitmap: (bits=");
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 7f827bbe982..6112c1c22f4 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -303,12 +303,10 @@ public:
my_decimal *val_decimal(my_decimal *);
bool val_bool();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- enum Item_result result_type() const;
- enum Item_result cmp_type() const;
- enum_field_types field_type() const;
+ const Type_handler *type_handler() const;
void fix_length_and_dec();
- uint cols();
+ uint cols() const;
Item* element_index(uint i) { return reinterpret_cast<Item*>(row[i]); }
Item** addr(uint i) { return (Item**)row + i; }
bool check_cols(uint c);
@@ -395,8 +393,7 @@ public:
}
void no_rows_in_result();
- enum Item_result result_type() const { return INT_RESULT;}
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
longlong val_int();
double val_real();
String *val_str(String*);
@@ -773,15 +770,13 @@ public:
};
-class subselect_engine: public Sql_alloc
+class subselect_engine: public Sql_alloc,
+ public Type_handler_hybrid_field_type
{
protected:
select_result_interceptor *result; /* results storage class */
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
- enum Item_result res_type; /* type of results */
- enum Item_result cmp_type; /* how to compare the results */
- enum_field_types res_field_type; /* column type of the results */
bool maybe_null; /* may be null (first item in select) */
public:
@@ -792,12 +787,11 @@ public:
subselect_engine(Item_subselect *si,
select_result_interceptor *res):
+ Type_handler_hybrid_field_type(&type_handler_varchar),
thd(NULL)
{
result= res;
item= si;
- cmp_type= res_type= STRING_RESULT;
- res_field_type= MYSQL_TYPE_VAR_STRING;
maybe_null= 0;
}
virtual ~subselect_engine() {}; // to satisfy compiler
@@ -832,11 +826,8 @@ public:
caller should call exec() again for the new engine.
*/
virtual int exec()= 0;
- virtual uint cols()= 0; /* return number of columns in select */
+ virtual uint cols() const= 0; /* return number of columns in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */
- enum Item_result type() { return res_type; }
- enum Item_result cmptype() { return cmp_type; }
- enum_field_types field_type() { return res_field_type; }
virtual void exclude()= 0;
virtual bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0;
@@ -872,7 +863,7 @@ public:
int prepare(THD *thd);
void fix_length_and_dec(Item_cache** row);
int exec();
- uint cols();
+ uint cols() const;
uint8 uncacheable();
void exclude();
table_map upper_select_const_tables();
@@ -907,7 +898,7 @@ public:
int prepare(THD *);
void fix_length_and_dec(Item_cache** row);
int exec();
- uint cols();
+ uint cols() const;
uint8 uncacheable();
void exclude();
table_map upper_select_const_tables();
@@ -965,7 +956,7 @@ public:
int prepare(THD *);
void fix_length_and_dec(Item_cache** row);
int exec();
- uint cols() { return 1; }
+ uint cols() const { return 1; }
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT_INJECTED; }
void exclude();
table_map upper_select_const_tables() { return 0; }
@@ -1103,7 +1094,7 @@ public:
int prepare(THD *);
int exec();
void print(String *str, enum_query_type query_type);
- uint cols() { return materialize_engine->cols(); }
+ uint cols() const { return materialize_engine->cols(); }
uint8 uncacheable() { return materialize_engine->uncacheable(); }
table_map upper_select_const_tables() { return 0; }
bool no_rows() { return !tmp_table->file->stats.records; }
@@ -1386,7 +1377,7 @@ public:
int prepare(THD *thd_arg) { set_thd(thd_arg); return 0; }
int exec();
void fix_length_and_dec(Item_cache**) {}
- uint cols() { /* TODO: what is the correct value? */ return 1; }
+ uint cols() const { /* TODO: what is the correct value? */ return 1; }
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; }
void exclude() {}
table_map upper_select_const_tables() { return 0; }
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 35e8dea46a7..97be5f15a8d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -879,7 +879,8 @@ bool Aggregator_distinct::setup(THD *thd)
if (always_null)
DBUG_RETURN(FALSE);
- Field *field= arg->make_num_distinct_aggregator_field(thd->mem_root, arg);
+ Field *field= arg->type_handler()->
+ make_num_distinct_aggregator_field(thd->mem_root, arg);
if (!field || !(table= create_virtual_tmp_table(thd, field)))
DBUG_RETURN(TRUE);
@@ -1137,37 +1138,12 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
if ((!item->fixed && item->fix_fields(thd, args)) ||
(item= args[0])->check_cols(1))
return TRUE;
- Type_std_attributes::set(args[0]);
with_subselect= args[0]->with_subselect;
- Item *item2= item->real_item();
- if (item2->type() == Item::FIELD_ITEM)
- set_handler_by_field_type(((Item_field*) item2)->field->type());
- else if (item->cmp_type() == TIME_RESULT)
- set_handler_by_field_type(item2->field_type());
- else
- set_handler_by_result_type(item2->result_type(),
- max_length, collation.collation);
-
- switch (Item_sum_hybrid::result_type()) {
- case INT_RESULT:
- case DECIMAL_RESULT:
- case STRING_RESULT:
- break;
- case REAL_RESULT:
- max_length= float_length(decimals);
- break;
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- };
+ fix_length_and_dec();
if (!is_window_func_sum_expr())
setup_hybrid(thd, args[0], NULL);
- /* MIN/MAX can return NULL for empty set indepedent of the used column */
- maybe_null= 1;
result_field=0;
- null_value=1;
- fix_length_and_dec();
if (check_sum_func(thd, ref))
return TRUE;
@@ -1178,6 +1154,14 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
}
+void Item_sum_hybrid::fix_length_and_dec()
+{
+ DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_type());
+ DBUG_ASSERT(args[0]->result_type() == args[0]->real_item()->result_type());
+ (void) args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
+}
+
+
/**
MIN/MAX function setup.
@@ -1197,14 +1181,14 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
void Item_sum_hybrid::setup_hybrid(THD *thd, Item *item, Item *value_arg)
{
- if (!(value= Item_cache::get_cache(thd, item, item->cmp_type())))
+ if (!(value= item->get_cache(thd)))
return;
value->setup(thd, item);
value->store(value_arg);
/* Don't cache value, as it will change */
if (!item->const_item())
value->set_used_tables(RAND_TABLE_BIT);
- if (!(arg_cache= Item_cache::get_cache(thd, item, item->cmp_type())))
+ if (!(arg_cache= item->get_cache(thd)))
return;
arg_cache->setup(thd, item);
/* Don't cache value, as it will change */
@@ -1213,51 +1197,20 @@ void Item_sum_hybrid::setup_hybrid(THD *thd, Item *item, Item *value_arg)
cmp= new Arg_comparator();
if (cmp)
cmp->set_cmp_func(this, (Item**)&arg_cache, (Item**)&value, FALSE);
- collation.set(item->collation);
}
Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table)
{
- Field *field;
- MEM_ROOT *mem_root;
-
if (args[0]->type() == Item::FIELD_ITEM)
{
- field= ((Item_field*) args[0])->field;
-
- if ((field= create_tmp_field_from_field(table->in_use, field, name, table,
- NULL)))
+ Field *field= ((Item_field*) args[0])->field;
+ if ((field= create_tmp_field_from_field(table->in_use, field, &name,
+ table, NULL)))
field->flags&= ~NOT_NULL_FLAG;
return field;
}
-
- /*
- DATE/TIME fields have STRING_RESULT result types.
- In order to preserve field type, it's needed to handle DATE/TIME
- fields creations separately.
- */
- mem_root= table->in_use->mem_root;
- switch (args[0]->field_type()) {
- case MYSQL_TYPE_DATE:
- field= new (mem_root)
- Field_newdate(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE, name);
- break;
- case MYSQL_TYPE_TIME:
- field= new_Field_time(mem_root, 0, maybe_null ? (uchar*)"" : 0, 0,
- Field::NONE, name, decimals);
- break;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME:
- field= new_Field_datetime(mem_root, 0, maybe_null ? (uchar*)"" : 0, 0,
- Field::NONE, name, decimals);
- break;
- default:
- return Item_sum::create_tmp_field(group, table);
- }
- if (field)
- field->init(table);
- return field;
+ return tmp_table_field_from_field_type(table);
}
@@ -1276,7 +1229,7 @@ Item_sum_sum::Item_sum_sum(THD *thd, Item_sum_sum *item)
count(item->count)
{
/* TODO: check if the following assignments are really needed */
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
my_decimal2decimal(item->dec_buffs, dec_buffs);
my_decimal2decimal(item->dec_buffs + 1, dec_buffs + 1);
@@ -1296,7 +1249,7 @@ void Item_sum_sum::clear()
DBUG_ENTER("Item_sum_sum::clear");
null_value=1;
count= 0;
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
curr_dec_buff= 0;
my_decimal_set_zero(dec_buffs);
@@ -1307,41 +1260,35 @@ void Item_sum_sum::clear()
}
+void Item_sum_sum::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double); // Change FLOAT to DOUBLE
+ decimals= args[0]->decimals;
+ sum= 0.0;
+}
+
+
+void Item_sum_sum::fix_length_and_dec_decimal()
+{
+ set_handler(&type_handler_newdecimal); // Change temporal to new DECIMAL
+ decimals= args[0]->decimals;
+ /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
+ int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+ curr_dec_buff= 0;
+ my_decimal_set_zero(dec_buffs);
+}
+
+
void Item_sum_sum::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
maybe_null=null_value=1;
- decimals= args[0]->decimals;
- switch (args[0]->cast_to_int_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
- sum= 0.0;
- break;
- case INT_RESULT:
- case TIME_RESULT:
- case DECIMAL_RESULT:
- {
- /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
- int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- curr_dec_buff= 0;
- set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
- my_decimal_set_zero(dec_buffs);
- break;
- }
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
- DBUG_PRINT("info", ("Type: %s (%d, %d)",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--"),
- max_length,
- (int)decimals));
+ args[0]->cast_to_int_type_handler()->Item_sum_sum_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
+ max_length, (int) decimals));
DBUG_VOID_RETURN;
}
@@ -1357,7 +1304,7 @@ void Item_sum_sum::add_helper(bool perform_removal)
{
DBUG_ENTER("Item_sum_sum::add_helper");
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
my_decimal value;
const my_decimal *val= aggr->arg_val_decimal(&value);
@@ -1414,7 +1361,7 @@ longlong Item_sum_sum::val_int()
DBUG_ASSERT(fixed == 1);
if (aggr)
aggr->endup();
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
longlong result;
my_decimal2int(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, unsigned_flag,
@@ -1430,7 +1377,7 @@ double Item_sum_sum::val_real()
DBUG_ASSERT(fixed == 1);
if (aggr)
aggr->endup();
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum);
return sum;
}
@@ -1440,7 +1387,7 @@ String *Item_sum_sum::val_str(String *str)
{
if (aggr)
aggr->endup();
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
return val_string_from_decimal(str);
return val_string_from_real(str);
}
@@ -1450,7 +1397,7 @@ my_decimal *Item_sum_sum::val_decimal(my_decimal *val)
{
if (aggr)
aggr->endup();
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
return null_value ? NULL : (dec_buffs + curr_dec_buff);
return val_decimal_from_real(val);
}
@@ -1642,28 +1589,39 @@ void Item_sum_count::cleanup()
/*
Avgerage
*/
+
+void Item_sum_avg::fix_length_and_dec_decimal()
+{
+ Item_sum_sum::fix_length_and_dec_decimal();
+ int precision= args[0]->decimal_precision() + prec_increment;
+ decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+ f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
+ f_scale= args[0]->decimals;
+ dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
+}
+
+
+void Item_sum_avg::fix_length_and_dec_double()
+{
+ Item_sum_sum::fix_length_and_dec_double();
+ decimals= MY_MIN(args[0]->decimals + prec_increment,
+ FLOATING_POINT_DECIMALS);
+ max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals));
+}
+
+
void Item_sum_avg::fix_length_and_dec()
{
- Item_sum_sum::fix_length_and_dec();
- maybe_null=null_value=1;
+ DBUG_ENTER("Item_sum_avg::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
- if (Item_sum_avg::result_type() == DECIMAL_RESULT)
- {
- int precision= args[0]->decimal_precision() + prec_increment;
- decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
- f_scale= args[0]->decimals;
- dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
- }
- else
- {
- decimals= MY_MIN(args[0]->decimals + prec_increment,
- FLOATING_POINT_DECIMALS);
- max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals));
- }
+ maybe_null=null_value=1;
+ args[0]->cast_to_int_type_handler()->Item_sum_avg_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
+ max_length, (int) decimals));
+ DBUG_VOID_RETURN;
}
@@ -1675,8 +1633,6 @@ Item *Item_sum_avg::copy_or_same(THD* thd)
Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table)
{
- Field *field;
- MEM_ROOT *mem_root= table->in_use->mem_root;
if (group)
{
@@ -1685,19 +1641,15 @@ Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table)
The easiest way is to do this is to store both value in a string
and unpack on access.
*/
- field= new (mem_root)
- Field_string(((Item_sum_avg::result_type() == DECIMAL_RESULT) ?
- dec_bin_size : sizeof(double)) + sizeof(longlong),
- 0, name, &my_charset_bin);
+ Field *field= new (table->in_use->mem_root)
+ Field_string(((result_type() == DECIMAL_RESULT) ?
+ dec_bin_size : sizeof(double)) + sizeof(longlong),
+ 0, &name, &my_charset_bin);
+ if (field)
+ field->init(table);
+ return field;
}
- else if (Item_sum_avg::result_type() == DECIMAL_RESULT)
- field= Field_new_decimal::create_from_item(mem_root, this);
- else
- field= new (mem_root) Field_double(max_length, maybe_null, name, decimals,
- TRUE);
- if (field)
- field->init(table);
- return field;
+ return tmp_table_field_from_field_type(table);
}
@@ -1758,7 +1710,7 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
For non-DECIMAL result_type() the division will be done in
Item_sum_avg::val_real().
*/
- if (Item_sum_avg::result_type() != DECIMAL_RESULT)
+ if (result_type() != DECIMAL_RESULT)
return val_decimal_from_real(val);
sum_dec= dec_buffs + curr_dec_buff;
@@ -1772,7 +1724,7 @@ String *Item_sum_avg::val_str(String *str)
{
if (aggr)
aggr->endup();
- if (Item_sum_avg::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
return val_string_from_decimal(str);
return val_string_from_real(str);
}
@@ -1862,6 +1814,25 @@ Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
}
+void Item_sum_variance::fix_length_and_dec_double()
+{
+ DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double);
+ decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS);
+}
+
+
+void Item_sum_variance::fix_length_and_dec_decimal()
+{
+ DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double);
+ int precision= args[0]->decimal_precision() * 2 + prec_increment;
+ decimals= MY_MIN(args[0]->decimals + prec_increment,
+ FLOATING_POINT_DECIMALS - 1);
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+}
+
+
void Item_sum_variance::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
@@ -1875,28 +1846,9 @@ void Item_sum_variance::fix_length_and_dec()
type.
*/
- switch (args[0]->result_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS);
- break;
- case INT_RESULT:
- case DECIMAL_RESULT:
- {
- int precision= args[0]->decimal_precision()*2 + prec_increment;
- decimals= MY_MIN(args[0]->decimals + prec_increment,
- FLOATING_POINT_DECIMALS-1);
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
-
- break;
- }
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- }
- DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals));
+ args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this);
+ DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
+ max_length, (int)decimals));
DBUG_VOID_RETURN;
}
@@ -1922,10 +1874,12 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table)
The easiest way is to do this is to store both value in a string
and unpack on access.
*/
- field= new Field_string(sizeof(double)*2 + sizeof(longlong), 0, name, &my_charset_bin);
+ field= new Field_string(sizeof(double)*2 + sizeof(longlong), 0,
+ &name, &my_charset_bin);
}
else
- field= new Field_double(max_length, maybe_null, name, decimals, TRUE);
+ field= new Field_double(max_length, maybe_null, &name, decimals,
+ TRUE);
if (field != NULL)
field->init(table);
@@ -2353,7 +2307,7 @@ void Item_sum_num::reset_field()
void Item_sum_hybrid::reset_field()
{
- switch(Item_sum_hybrid::result_type()) {
+ switch(result_type()) {
case STRING_RESULT:
{
char buff[MAX_FIELD_WIDTH];
@@ -2436,7 +2390,7 @@ void Item_sum_hybrid::reset_field()
void Item_sum_sum::reset_field()
{
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
if (!arg_val) // Null
@@ -2472,7 +2426,7 @@ void Item_sum_avg::reset_field()
{
uchar *res=result_field->ptr;
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (Item_sum_avg::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
longlong tmp;
my_decimal value, *arg_dec= args[0]->val_decimal(&value);
@@ -2530,7 +2484,7 @@ void Item_sum_bit::update_field()
void Item_sum_sum::update_field()
{
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (Item_sum_sum::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
if (!args[0]->null_value)
@@ -2585,7 +2539,7 @@ void Item_sum_avg::update_field()
DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
- if (Item_sum_avg::result_type() == DECIMAL_RESULT)
+ if (result_type() == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
if (!args[0]->null_value)
@@ -2624,7 +2578,7 @@ void Item_sum_avg::update_field()
Item *Item_sum_avg::result_item(THD *thd, Field *field)
{
return
- Item_sum_avg::result_type() == DECIMAL_RESULT ?
+ result_type() == DECIMAL_RESULT ?
(Item_avg_field*) new (thd->mem_root) Item_avg_field_decimal(thd, this) :
(Item_avg_field*) new (thd->mem_root) Item_avg_field_double(thd, this);
}
@@ -2632,7 +2586,7 @@ Item *Item_sum_avg::result_item(THD *thd, Field *field)
void Item_sum_hybrid::update_field()
{
- switch (Item_sum_hybrid::result_type()) {
+ switch (result_type()) {
case STRING_RESULT:
min_max_update_str_field();
break;
@@ -3364,24 +3318,6 @@ void Item_func_group_concat::cleanup()
}
-Field *Item_func_group_concat::make_string_field(TABLE *table_arg)
-{
- Field *field;
- DBUG_ASSERT(collation.collation);
- if (too_big_for_varchar())
- field= new Field_blob(max_length,
- maybe_null, name, collation.collation, TRUE);
- else
- field= new Field_varstring(max_length,
- maybe_null, name, table_arg->s,
- collation.collation);
-
- if (field)
- field->init(table_arg);
- return field;
-}
-
-
Item *Item_func_group_concat::copy_or_same(THD* thd)
{
return new (thd->mem_root) Item_func_group_concat(thd, this);
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 852df778087..a160d0ee522 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -456,7 +456,6 @@ public:
Updated value is then saved in the field.
*/
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 Item *result_item(THD *thd, Field *field);
@@ -510,10 +509,7 @@ public:
}
virtual void make_unique() { force_copy_fields= TRUE; }
Item *get_tmp_table_item(THD *thd);
- Field *create_tmp_field(bool group, TABLE *table)
- {
- return Item::create_tmp_field(group, table, MY_INT32_NUM_DECIMAL_DIGITS);
- }
+ Field *create_tmp_field(bool group, TABLE *table);
virtual bool collect_outer_ref_processor(void *param);
bool init_sum_func_check(THD *thd);
bool check_sum_func(THD *thd, Item **ref);
@@ -521,7 +517,7 @@ public:
st_select_lex *depended_from()
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
- Item *get_arg(uint i) { return args[i]; }
+ Item *get_arg(uint i) const { return args[i]; }
Item *set_arg(uint i, THD *thd, Item *new_val);
uint get_arg_count() const { return arg_count; }
@@ -750,8 +746,7 @@ public:
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
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; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
void fix_length_and_dec()
{ decimals=0; max_length=21; maybe_null=null_value=0; }
};
@@ -783,12 +778,10 @@ public:
longlong val_int();
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
void reset_field();
void update_field();
void no_rows_in_result() {}
@@ -888,6 +881,8 @@ public:
:Item_sum_sum(thd, item), count(item->count),
prec_increment(item->prec_increment) {}
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
void fix_length_and_dec();
enum Sumfunctype sum_func () const
{
@@ -962,6 +957,8 @@ public:
{}
Item_sum_variance(THD *thd, Item_sum_variance *item);
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
void clear();
bool add();
double val_real();
@@ -974,8 +971,7 @@ public:
{ return sample ? "var_samp(" : "variance("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table);
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;}
+ const Type_handler *type_handler() const { return &type_handler_double; }
void cleanup()
{
count= 0;
@@ -1021,7 +1017,7 @@ protected:
public:
Item_sum_hybrid(THD *thd, Item *item_par,int sign):
Item_sum(thd, item_par),
- Type_handler_hybrid_field_type(MYSQL_TYPE_LONGLONG),
+ Type_handler_hybrid_field_type(&type_handler_longlong),
value(0), arg_cache(0), cmp(0),
cmp_sign(sign), was_values(TRUE)
{ collation.set(&my_charset_bin); }
@@ -1032,6 +1028,7 @@ protected:
cmp_sign(item->cmp_sign), was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
+ void fix_length_and_dec();
void setup_hybrid(THD *thd, Item *item, Item *value_arg);
void clear();
double val_real();
@@ -1039,13 +1036,13 @@ protected:
my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
- bool keep_field_type(void) const { return 1; }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
- enum enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
+ const Type_handler *real_type_handler() const
+ {
+ return get_arg(0)->real_type_handler();
+ }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
+ TYPELIB *get_typelib() const { return args[0]->get_typelib(); }
void update_field();
void min_max_update_str_field();
void min_max_update_real_field();
@@ -1141,7 +1138,7 @@ public:
}
protected:
- static const int NUM_BIT_COUNTERS= 64;
+ enum bit_counters { NUM_BIT_COUNTERS= 64 };
ulonglong reset_bits,bits;
/*
Marks whether the function is to be computed as a window function.
@@ -1227,7 +1224,7 @@ public:
void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); }
bool check_vcol_func_processor(void *arg)
{
- return mark_unsupported_function(name, arg, VCOL_IMPOSSIBLE);
+ return mark_unsupported_function(name.str, arg, VCOL_IMPOSSIBLE);
}
};
@@ -1251,8 +1248,7 @@ public:
Item_avg_field_double(THD *thd, Item_sum_avg *item)
:Item_avg_field(thd, item)
{ }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- enum Item_result result_type () const { return REAL_RESULT; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
longlong val_int() { return val_int_from_real(); }
my_decimal *val_decimal(my_decimal *dec) { return val_decimal_from_real(dec); }
String *val_str(String *str) { return val_string_from_real(str); }
@@ -1272,8 +1268,7 @@ public:
f_scale(item->f_scale),
dec_bin_size(item->dec_bin_size)
{ }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
- enum Item_result result_type () const { return DECIMAL_RESULT; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
double val_real() { return val_real_from_decimal(); }
longlong val_int() { return val_int_from_decimal(); }
String *val_str(String *str) { return val_string_from_decimal(str); }
@@ -1298,8 +1293,7 @@ public:
my_decimal *val_decimal(my_decimal *dec_buf)
{ return val_decimal_from_real(dec_buf); }
bool is_null() { update_null_value(); return null_value; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- enum Item_result result_type () const { return REAL_RESULT; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_variance_field>(thd, mem_root, this); }
};
@@ -1397,9 +1391,7 @@ class Item_sum_udf_float :public Item_udf_sum
double val_real();
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- 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; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1421,8 +1413,7 @@ public:
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
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; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
void fix_length_and_dec() { decimals=0; max_length=21; }
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1463,8 +1454,7 @@ public:
return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used);
}
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(); }
+ const Type_handler *type_handler() const { return string_type_handler(); }
void fix_length_and_dec();
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1485,8 +1475,7 @@ public:
double val_real();
longlong val_int();
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; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1561,7 +1550,6 @@ public:
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
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; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
void clear() {}
@@ -1624,9 +1612,6 @@ class Item_func_group_concat : public Item_sum
friend int dump_leaf_key(void* key_arg,
element_count count __attribute__((unused)),
void* item_arg);
-protected:
- virtual Field *make_string_field(TABLE *table);
-
public:
Item_func_group_concat(THD *thd, Name_resolution_context *context_arg,
bool is_distinct, List<Item> *is_select,
@@ -1638,14 +1623,11 @@ public:
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat("; }
- virtual Item_result result_type () const { return STRING_RESULT; }
- virtual Item_result cmp_type () const { return STRING_RESULT; }
- enum_field_types field_type() const
+ const Type_handler *type_handler() const
{
if (too_big_for_varchar())
- return MYSQL_TYPE_BLOB;
- else
- return MYSQL_TYPE_VARCHAR;
+ return &type_handler_blob;
+ return &type_handler_varchar;
}
void clear();
bool add();
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 70f160991d0..e0ee85dd5a2 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1458,34 +1458,6 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
}
-void Item_temporal_func::fix_length_and_dec()
-{
- uint char_length= mysql_temporal_int_part_length(field_type());
- /*
- We set maybe_null to 1 as default as any bad argument with date or
- time can get us to return NULL.
- */
- maybe_null= (arg_count > 0);
- if (decimals)
- {
- if (decimals == NOT_FIXED_DEC)
- char_length+= TIME_SECOND_PART_DIGITS + 1;
- else
- {
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
- char_length+= decimals + 1;
- }
- }
- sql_mode= current_thd->variables.sql_mode &
- (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE);
- collation.set(field_type() == MYSQL_TYPE_STRING ?
- default_charset() : &my_charset_numeric,
- field_type() == MYSQL_TYPE_STRING ?
- DERIVATION_COERCIBLE : DERIVATION_NUMERIC,
- MY_REPERTOIRE_ASCII);
- fix_char_length(char_length);
-}
-
String *Item_temporal_func::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -1560,7 +1532,7 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str)
/* Check that the returned timestamp type matches to the function type */
DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING ||
ltime.time_type == MYSQL_TIMESTAMP_NONE ||
- mysql_type_to_time_type(field_type()) == ltime.time_type);
+ ltime.time_type == mysql_timestamp_type());
return str;
}
@@ -2009,8 +1981,8 @@ void 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();
+ fix_attributes_datetime_not_fixed_dec(args[0]->decimals);
+ maybe_null= true;
}
@@ -2037,13 +2009,6 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
}
-void Item_func_convert_tz::fix_length_and_dec()
-{
- decimals= args[0]->temporal_precision(MYSQL_TYPE_DATETIME);
- Item_temporal_func::fix_length_and_dec();
-}
-
-
bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime,
ulonglong fuzzy_date __attribute__((unused)))
{
@@ -2093,6 +2058,13 @@ void Item_date_add_interval::fix_length_and_dec()
{
enum_field_types arg0_field_type;
+ if (!args[0]->type_handler()->is_traditional_type())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ args[0]->type_handler()->name().ptr(),
+ "interval", func_name());
+ return;
+ }
/*
The field type for the result of an Item_datefunc is defined as
follows:
@@ -2108,7 +2080,6 @@ void Item_date_add_interval::fix_length_and_dec()
(This is because you can't know if the string contains a DATE,
MYSQL_TIME or DATETIME argument)
*/
- set_handler_by_field_type(MYSQL_TYPE_STRING);
arg0_field_type= args[0]->field_type();
uint interval_dec= 0;
if (int_type == INTERVAL_MICROSECOND ||
@@ -2121,30 +2092,45 @@ void Item_date_add_interval::fix_length_and_dec()
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
{
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
+ uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
+ set_handler(&type_handler_datetime);
+ fix_attributes_datetime(dec);
}
else if (arg0_field_type == MYSQL_TYPE_DATE)
{
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
- set_handler_by_field_type(arg0_field_type);
+ {
+ set_handler(&type_handler_newdate);
+ fix_attributes_date();
+ }
else
{
- decimals= interval_dec;
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(interval_dec);
}
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
+ uint dec= MY_MAX(args[0]->time_precision(), interval_dec);
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
- set_handler_by_field_type(arg0_field_type);
+ {
+ set_handler(&type_handler_time2);
+ fix_attributes_time(dec);
+ }
else
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
+ {
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(dec);
+ }
}
else
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
- Item_temporal_func::fix_length_and_dec();
+ {
+ uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
+ set_handler(&type_handler_string);
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
+ fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
+ }
+ maybe_null= true;
}
@@ -2502,7 +2488,23 @@ end:
}
-void Item_char_typecast::fix_length_and_dec()
+void Item_char_typecast::fix_length_and_dec_numeric()
+{
+ fix_length_and_dec_internal(from_cs= cast_cs->mbminlen == 1 ?
+ cast_cs :
+ &my_charset_latin1);
+}
+
+
+void Item_char_typecast::fix_length_and_dec_str()
+{
+ fix_length_and_dec_internal(from_cs= args[0]->dynamic_result() ?
+ 0 :
+ args[0]->collation.collation);
+}
+
+
+void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs)
{
uint32 char_length;
/*
@@ -2532,12 +2534,6 @@ void Item_char_typecast::fix_length_and_dec()
Note (TODO): we could use repertoire technique here.
*/
- from_cs= ((args[0]->result_type() == INT_RESULT ||
- args[0]->result_type() == DECIMAL_RESULT ||
- args[0]->result_type() == REAL_RESULT) ?
- (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
- args[0]->dynamic_result() ? 0 :
- args[0]->collation.collation);
charset_conversion= !from_cs || (cast_cs->mbmaxlen > 1) ||
(!my_charset_same(from_cs, cast_cs) &&
from_cs != &my_charset_bin &&
@@ -2639,8 +2635,15 @@ err:
void Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
- decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
+ if (!args[0]->type_handler()->is_traditional_type() ||
+ !args[1]->type_handler()->is_traditional_type())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ args[0]->type_handler()->name().ptr(),
+ args[1]->type_handler()->name().ptr(), func_name());
+ return;
+ }
/*
The field type for the result of an Item_func_add_time function is defined
as follows:
@@ -2651,24 +2654,30 @@ void Item_func_add_time::fix_length_and_dec()
- Otherwise the result is MYSQL_TYPE_STRING
*/
- set_handler_by_field_type(MYSQL_TYPE_STRING);
arg0_field_type= args[0]->field_type();
if (arg0_field_type == MYSQL_TYPE_DATE ||
arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP ||
is_date)
{
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ uint dec= MY_MAX(args[0]->datetime_precision(), args[1]->time_precision());
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(dec);
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
- set_handler_by_field_type(MYSQL_TYPE_TIME);
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
+ set_handler(&type_handler_time2);
+ fix_attributes_time(dec);
+ }
+ else
+ {
+ uint dec= MY_MAX(args[0]->decimals, args[1]->decimals);
+ set_handler(&type_handler_string);
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
+ fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
}
- Item_temporal_func::fix_length_and_dec();
+ maybe_null= true;
}
/**
@@ -3159,6 +3168,14 @@ get_date_time_result_type(const char *format, uint length)
void Item_func_str_to_date::fix_length_and_dec()
{
+ if (!args[0]->type_handler()->is_traditional_type() ||
+ !args[1]->type_handler()->is_traditional_type())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ args[0]->type_handler()->name().ptr(),
+ args[1]->type_handler()->name().ptr(), func_name());
+ return;
+ }
if (agg_arg_charsets(collation, args, 2, MY_COLL_ALLOW_CONV, 1))
return;
if (collation.collation->mbminlen > 1)
@@ -3170,8 +3187,10 @@ void Item_func_str_to_date::fix_length_and_dec()
#endif
}
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
- decimals= TIME_SECOND_PART_DIGITS;
+ maybe_null= true;
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
+
if ((const_item= args[1]->const_item()))
{
char format_buff[64];
@@ -3185,25 +3204,29 @@ void Item_func_str_to_date::fix_length_and_dec()
get_date_time_result_type(format->ptr(), format->length());
switch (cached_format_type) {
case DATE_ONLY:
- set_handler_by_field_type(MYSQL_TYPE_DATE);
+ set_handler(&type_handler_newdate);
+ fix_attributes_date();
break;
case TIME_MICROSECOND:
- decimals= 6;
- /* fall through */
+ set_handler(&type_handler_time2);
+ fix_attributes_time(TIME_SECOND_PART_DIGITS);
+ break;
case TIME_ONLY:
- set_handler_by_field_type(MYSQL_TYPE_TIME);
+ set_handler(&type_handler_time2);
+ fix_attributes_time(0);
break;
case DATE_TIME_MICROSECOND:
- decimals= 6;
- /* fall through */
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
+ break;
case DATE_TIME:
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(0);
break;
}
}
}
- cached_timestamp_type= mysql_type_to_time_type(field_type());
- Item_temporal_func::fix_length_and_dec();
+ cached_timestamp_type= mysql_timestamp_type();
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index d8f69e2098d..4cdf7b63158 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -31,22 +31,12 @@ enum date_time_format_types
};
-static inline uint
-mysql_temporal_int_part_length(enum enum_field_types mysql_type)
-{
- static uint max_time_type_width[5]=
- { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
- MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
- return max_time_type_width[mysql_type_to_time_type(mysql_type)+2];
-}
-
-
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
-class Item_func_period_add :public Item_int_func
+class Item_func_period_add :public Item_long_func
{
public:
- Item_func_period_add(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_period_add(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_add"; }
void fix_length_and_dec()
@@ -58,10 +48,10 @@ public:
};
-class Item_func_period_diff :public Item_int_func
+class Item_func_period_diff :public Item_long_func
{
public:
- Item_func_period_diff(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_period_diff(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_diff"; }
void fix_length_and_dec()
@@ -74,10 +64,10 @@ public:
};
-class Item_func_to_days :public Item_int_func
+class Item_func_to_days :public Item_long_func
{
public:
- Item_func_to_days(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_to_days(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_days"; }
void fix_length_and_dec()
@@ -99,16 +89,16 @@ public:
};
-class Item_func_to_seconds :public Item_int_func
+class Item_func_to_seconds :public Item_longlong_func
{
public:
- Item_func_to_seconds(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_to_seconds(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_seconds"; }
void fix_length_and_dec()
{
decimals=0;
- max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ fix_char_length(12);
maybe_null= 1;
}
enum_monotonicity_info get_monotonicity_info() const;
@@ -125,10 +115,10 @@ public:
};
-class Item_func_dayofmonth :public Item_int_func
+class Item_func_dayofmonth :public Item_long_func
{
public:
- Item_func_dayofmonth(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dayofmonth(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofmonth"; }
void fix_length_and_dec()
@@ -165,8 +155,7 @@ public:
return str;
}
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; }
+ const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
{
decimals= 0;
@@ -207,10 +196,10 @@ public:
};
-class Item_func_dayofyear :public Item_int_func
+class Item_func_dayofyear :public Item_long_func
{
public:
- Item_func_dayofyear(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dayofyear(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofyear"; }
void fix_length_and_dec()
@@ -230,10 +219,10 @@ public:
};
-class Item_func_hour :public Item_int_func
+class Item_func_hour :public Item_long_func
{
public:
- Item_func_hour(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_hour(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "hour"; }
void fix_length_and_dec()
@@ -253,10 +242,10 @@ public:
};
-class Item_func_minute :public Item_int_func
+class Item_func_minute :public Item_long_func
{
public:
- Item_func_minute(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_minute(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "minute"; }
void fix_length_and_dec()
@@ -276,10 +265,10 @@ public:
};
-class Item_func_quarter :public Item_int_func
+class Item_func_quarter :public Item_long_func
{
public:
- Item_func_quarter(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_quarter(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "quarter"; }
void fix_length_and_dec()
@@ -299,10 +288,10 @@ public:
};
-class Item_func_second :public Item_int_func
+class Item_func_second :public Item_long_func
{
public:
- Item_func_second(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_second(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "second"; }
void fix_length_and_dec()
@@ -322,11 +311,11 @@ public:
};
-class Item_func_week :public Item_int_func
+class Item_func_week :public Item_long_func
{
public:
- Item_func_week(THD *thd, Item *a): Item_int_func(thd, a) {}
- Item_func_week(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_week(THD *thd, Item *a): Item_long_func(thd, a) {}
+ Item_func_week(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "week"; }
void fix_length_and_dec()
@@ -349,10 +338,10 @@ public:
{ return get_item_copy<Item_func_week>(thd, mem_root, this); }
};
-class Item_func_yearweek :public Item_int_func
+class Item_func_yearweek :public Item_long_func
{
public:
- Item_func_yearweek(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_yearweek(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "yearweek"; }
void fix_length_and_dec()
@@ -372,10 +361,10 @@ public:
};
-class Item_func_year :public Item_int_func
+class Item_func_year :public Item_long_func
{
public:
- Item_func_year(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_year(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "year"; }
enum_monotonicity_info get_monotonicity_info() const;
@@ -415,8 +404,7 @@ public:
{
return (odbc_type ? "dayofweek" : "weekday");
}
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
{
decimals= 0;
@@ -440,8 +428,7 @@ class Item_func_dayname :public Item_func_weekday
Item_func_dayname(THD *thd, Item *a): Item_func_weekday(thd, a, 0) {}
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
void fix_length_and_dec();
bool check_partition_func_processor(void *int_arg) {return TRUE;}
bool check_vcol_func_processor(void *arg)
@@ -453,19 +440,19 @@ class Item_func_dayname :public Item_func_weekday
class Item_func_seconds_hybrid: public Item_func_numhybrid
{
-protected:
- virtual enum_field_types arg0_expected_type() const = 0;
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()
+ void fix_length_and_dec_generic(uint dec)
{
- if (arg_count)
- decimals= args[0]->temporal_precision(arg0_expected_type());
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ decimals= dec;
max_length=17 + (decimals ? decimals + 1 : 0);
maybe_null= true;
- set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT);
+ if (decimals)
+ set_handler(&type_handler_newdecimal);
+ else
+ set_handler(type_handler_long_or_longlong());
}
double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
@@ -476,8 +463,6 @@ public:
class Item_func_unix_timestamp :public Item_func_seconds_hybrid
{
bool get_timestamp_value(my_time_t *seconds, ulong *second_part);
-protected:
- enum_field_types arg0_expected_type() const { return MYSQL_TYPE_DATETIME; }
public:
Item_func_unix_timestamp(THD *thd): Item_func_seconds_hybrid(thd) {}
Item_func_unix_timestamp(THD *thd, Item *a):
@@ -501,6 +486,10 @@ public:
return FALSE;
return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
}
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0);
+ }
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -510,8 +499,6 @@ public:
class Item_func_time_to_sec :public Item_func_seconds_hybrid
{
-protected:
- enum_field_types arg0_expected_type() const { return MYSQL_TYPE_TIME; }
public:
Item_func_time_to_sec(THD *thd, Item *item):
Item_func_seconds_hybrid(thd, item) {}
@@ -522,6 +509,10 @@ public:
{
return !has_time_args();
}
+ void fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(args[0]->time_precision());
+ }
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -531,25 +522,19 @@ public:
class Item_temporal_func: public Item_func
{
- sql_mode_t sql_mode;
public:
Item_temporal_func(THD *thd): Item_func(thd) {}
Item_temporal_func(THD *thd, Item *a): Item_func(thd, a) {}
Item_temporal_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {}
Item_temporal_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) {}
- enum Item_result result_type () const { return STRING_RESULT; }
- Item_result cmp_type() const { return TIME_RESULT; }
String *val_str(String *str);
longlong val_int() { return val_int_from_date(); }
double val_real() { return val_real_from_date(); }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; }
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table, false, false); }
int save_in_field(Field *field, bool no_conversions)
- { return save_date_in_field(field); }
- void fix_length_and_dec();
+ { return save_date_in_field(field, no_conversions); }
};
@@ -557,32 +542,20 @@ public:
Abstract class for functions returning TIME, DATE, DATETIME or string values,
whose data type depends on parameters and is set at fix_fields time.
*/
-class Item_temporal_hybrid_func: public Item_temporal_func,
- public Type_handler_hybrid_field_type
+class Item_temporal_hybrid_func: public Item_hybrid_func
{
protected:
String ascii_buf; // Conversion buffer
public:
Item_temporal_hybrid_func(THD *thd, Item *a, Item *b):
- Item_temporal_func(thd, a, b) {}
- enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
- enum Item_result result_type () const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type () const
- { return Type_handler_hybrid_field_type::cmp_type(); }
- CHARSET_INFO *charset_for_protocol() const
- {
- /*
- Can return TIME, DATE, DATETIME or VARCHAR depending on arguments.
- Send using "binary" when TIME, DATE or DATETIME,
- or using collation.collation when VARCHAR
- (which is fixed from @@collation_connection in fix_length_and_dec).
- */
- DBUG_ASSERT(fixed == 1);
- return Item_temporal_hybrid_func::field_type() == MYSQL_TYPE_STRING ?
- collation.collation : &my_charset_bin;
- }
+ Item_hybrid_func(thd, a, b) {}
+
+ longlong val_int() { return val_int_from_date(); }
+ double val_real() { return val_real_from_date(); }
+ bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)= 0;
+ my_decimal *val_decimal(my_decimal *decimal_value)
+ { return val_decimal_from_date(decimal_value); }
+
/**
Fix the returned timestamp to match field_type(),
which is important for val_str().
@@ -607,7 +580,13 @@ class Item_datefunc :public Item_temporal_func
public:
Item_datefunc(THD *thd): Item_temporal_func(thd) { }
Item_datefunc(THD *thd, Item *a): Item_temporal_func(thd, a) { }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ Item_datefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) { }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
+ void fix_length_and_dec()
+ {
+ fix_attributes_date();
+ maybe_null= (arg_count > 0);
+ }
};
@@ -619,7 +598,7 @@ public:
Item_timefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) {}
Item_timefunc(THD *thd, Item *a, Item *b, Item *c):
Item_temporal_func(thd, a, b ,c) {}
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ const Type_handler *type_handler() const { return &type_handler_time2; }
};
@@ -630,7 +609,7 @@ public:
Item_datetimefunc(THD *thd, Item *a): Item_temporal_func(thd, a) {}
Item_datetimefunc(THD *thd, Item *a, Item *b, Item *c):
Item_temporal_func(thd, a, b ,c) {}
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ const Type_handler *type_handler() const { return &type_handler_datetime2; }
};
@@ -644,6 +623,7 @@ public:
Item_func_curtime(THD *thd, uint dec): Item_timefunc(thd), last_query_id(0)
{ decimals= dec; }
bool fix_fields(THD *, Item **);
+ void fix_length_and_dec() { fix_attributes_time(decimals); }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
/*
Abstract method that defines which time zone is used for conversion.
@@ -731,6 +711,7 @@ public:
Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd), last_query_id(0)
{ decimals= dec; }
bool fix_fields(THD *, Item **);
+ void fix_length_and_dec() { fix_attributes_datetime(decimals); }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
bool check_vcol_func_processor(void *arg)
@@ -880,7 +861,11 @@ 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();
+ void fix_length_and_dec()
+ {
+ fix_attributes_datetime(args[0]->datetime_precision());
+ maybe_null= true;
+ }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void cleanup();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -895,8 +880,8 @@ public:
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void fix_length_and_dec()
{
- decimals= MY_MIN(args[0]->decimals, TIME_SECOND_PART_DIGITS);
- Item_timefunc::fix_length_and_dec();
+ fix_attributes_time(args[0]->decimals);
+ maybe_null= true;
}
const char *func_name() const { return "sec_to_time"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -948,7 +933,7 @@ class Item_extract :public Item_int_func
const interval_type int_type; // keep it public
Item_extract(THD *thd, interval_type type_arg, Item *a):
Item_int_func(thd, a), int_type(type_arg) {}
- enum_field_types field_type() const
+ const Type_handler *type_handler() const
{
switch (int_type) {
case INTERVAL_YEAR:
@@ -968,16 +953,16 @@ class Item_extract :public Item_int_func
case INTERVAL_SECOND:
case INTERVAL_MICROSECOND:
case INTERVAL_SECOND_MICROSECOND:
- return MYSQL_TYPE_LONG;
+ return &type_handler_long;
case INTERVAL_DAY_MICROSECOND:
case INTERVAL_HOUR_MICROSECOND:
case INTERVAL_MINUTE_MICROSECOND:
- return MYSQL_TYPE_LONGLONG;
+ return &type_handler_longlong;
case INTERVAL_LAST:
break;
}
DBUG_ASSERT(0);
- return MYSQL_TYPE_LONGLONG;
+ return &type_handler_longlong;
}
longlong val_int();
enum Functype functype() const { return EXTRACT_FUNC; }
@@ -1028,9 +1013,6 @@ class Item_extract :public Item_int_func
}
return true;
}
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table, false, false); }
-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_extract>(thd, mem_root, this); }
};
@@ -1047,14 +1029,21 @@ class Item_char_typecast :public Item_str_func
String *copy(String *src, CHARSET_INFO *cs);
uint adjusted_length_with_warn(uint length);
void check_truncation_with_warn(String *src, uint dstlen);
+ void fix_length_and_dec_internal(CHARSET_INFO *fromcs);
public:
Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg):
Item_str_func(thd, a), cast_length(length_arg), cast_cs(cs_arg) {}
enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "cast_as_char"; }
+ CHARSET_INFO *cast_charset() const { return cast_cs; }
String *val_str(String *a);
- void fix_length_and_dec();
+ void fix_length_and_dec_numeric();
+ void fix_length_and_dec_str();
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
+ }
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)
@@ -1068,12 +1057,6 @@ public:
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()
- {
- if (decimals == NOT_FIXED_DEC)
- decimals= args[0]->temporal_precision(field_type());
- Item_temporal_func::fix_length_and_dec();
- }
};
class Item_date_typecast :public Item_temporal_typecast
@@ -1083,7 +1066,11 @@ public:
const char *func_name() const { return "cast_as_date"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "date"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_date_typecast>(thd, mem_root, this); }
};
@@ -1097,7 +1084,11 @@ public:
const char *func_name() const { return "cast_as_time"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "time"; }
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ const Type_handler *type_handler() const { return &type_handler_time2; }
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_time_typecast_fix_length_and_dec(this);
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_time_typecast>(thd, mem_root, this); }
};
@@ -1110,20 +1101,23 @@ public:
Item_temporal_typecast(thd, a) { decimals= dec_arg; }
const char *func_name() const { return "cast_as_datetime"; }
const char *cast_type() const { return "datetime"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ const Type_handler *type_handler() const { return &type_handler_datetime2; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
+ void fix_length_and_dec()
+ {
+ args[0]->type_handler()->Item_datetime_typecast_fix_length_and_dec(this);
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_datetime_typecast>(thd, mem_root, this); }
};
-class Item_func_makedate :public Item_temporal_func
+class Item_func_makedate :public Item_datefunc
{
public:
Item_func_makedate(THD *thd, Item *a, Item *b):
- Item_temporal_func(thd, a, b) {}
+ Item_datefunc(thd, a, b) {}
const char *func_name() const { return "makedate"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_makedate>(thd, mem_root, this); }
@@ -1154,9 +1148,9 @@ public:
const char *func_name() const { return "timediff"; }
void 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();
+ uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
+ fix_attributes_time(dec);
+ maybe_null= true;
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -1171,8 +1165,8 @@ public:
{}
void fix_length_and_dec()
{
- decimals= MY_MIN(args[2]->decimals, TIME_SECOND_PART_DIGITS);
- Item_timefunc::fix_length_and_dec();
+ fix_attributes_time(args[2]->decimals);
+ maybe_null= true;
}
const char *func_name() const { return "maketime"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
@@ -1181,16 +1175,17 @@ public:
};
-class Item_func_microsecond :public Item_int_func
+class Item_func_microsecond :public Item_long_func
{
public:
- Item_func_microsecond(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_microsecond(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "microsecond"; }
void fix_length_and_dec()
{
decimals=0;
maybe_null=1;
+ fix_char_length(6);
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -1203,12 +1198,12 @@ public:
};
-class Item_func_timestamp_diff :public Item_int_func
+class Item_func_timestamp_diff :public Item_longlong_func
{
const interval_type int_type;
public:
Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg):
- Item_int_func(thd, a, b), int_type(type_arg) {}
+ Item_longlong_func(thd, a, b), int_type(type_arg) {}
const char *func_name() const { return "timestampdiff"; }
longlong val_int();
void fix_length_and_dec()
diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc
index 27b007201c5..a216930cad6 100644
--- a/sql/item_windowfunc.cc
+++ b/sql/item_windowfunc.cc
@@ -13,7 +13,7 @@ Item_window_func::resolve_window_name(THD *thd)
return false;
}
DBUG_ASSERT(window_name != NULL && window_spec == NULL);
- char *ref_name= window_name->str;
+ const char *ref_name= window_name->str;
/* !TODO: Add the code to resolve ref_name in outer queries */
/*
@@ -26,7 +26,7 @@ Item_window_func::resolve_window_name(THD *thd)
Window_spec *win_spec;
while((win_spec= it++))
{
- char *win_spec_name= win_spec->name();
+ const char *win_spec_name= win_spec->name();
if (win_spec_name &&
my_strcasecmp(system_charset_info, ref_name, win_spec_name) == 0)
{
@@ -243,14 +243,14 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref)
Item *item2= args[0]->real_item();
if (item2->type() == Item::FIELD_ITEM)
- set_handler_by_field_type(((Item_field*) item2)->field->type());
+ set_handler(item2->type_handler());
else if (args[0]->cmp_type() == TIME_RESULT)
- set_handler_by_field_type(item2->field_type());
+ set_handler(item2->type_handler());
else
set_handler_by_result_type(item2->result_type(),
max_length, collation.collation);
- switch (Item_sum_hybrid_simple::result_type()) {
+ switch (result_type()) {
case INT_RESULT:
case DECIMAL_RESULT:
case STRING_RESULT:
@@ -290,7 +290,7 @@ bool Item_sum_hybrid_simple::add()
void Item_sum_hybrid_simple::setup_hybrid(THD *thd, Item *item)
{
- if (!(value= Item_cache::get_cache(thd, item, item->cmp_type())))
+ if (!(value= item->get_cache(thd)))
return;
value->setup(thd, item);
value->store(item);
@@ -352,7 +352,7 @@ Field *Item_sum_hybrid_simple::create_tmp_field(bool group, TABLE *table)
void Item_sum_hybrid_simple::reset_field()
{
- switch(Item_sum_hybrid_simple::result_type()) {
+ switch(result_type()) {
case STRING_RESULT:
{
char buff[MAX_FIELD_WIDTH];
diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h
index 0dee60915f8..9fe95ed6cee 100644
--- a/sql/item_windowfunc.h
+++ b/sql/item_windowfunc.h
@@ -285,13 +285,13 @@ class Item_sum_hybrid_simple : public Item_sum,
public:
Item_sum_hybrid_simple(THD *thd, Item *arg):
Item_sum(thd, arg),
- Type_handler_hybrid_field_type(MYSQL_TYPE_LONGLONG),
+ Type_handler_hybrid_field_type(&type_handler_longlong),
value(NULL)
{ collation.set(&my_charset_bin); }
Item_sum_hybrid_simple(THD *thd, Item *arg1, Item *arg2):
Item_sum(thd, arg1, arg2),
- Type_handler_hybrid_field_type(MYSQL_TYPE_LONGLONG),
+ Type_handler_hybrid_field_type(&type_handler_longlong),
value(NULL)
{ collation.set(&my_charset_bin); }
@@ -303,14 +303,8 @@ class Item_sum_hybrid_simple : public Item_sum,
my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
- /* TODO(cvicentiu) copied from Item_sum_hybrid, what does it do? */
- bool keep_field_type(void) const { return 1; }
- enum Item_result result_type() const
- { return Type_handler_hybrid_field_type::result_type(); }
- enum Item_result cmp_type() const
- { return Type_handler_hybrid_field_type::cmp_type(); }
- enum enum_field_types field_type() const
- { return Type_handler_hybrid_field_type::field_type(); }
+ const Type_handler *type_handler() const
+ { return Type_handler_hybrid_field_type::type_handler(); }
void update_field();
Field *create_tmp_field(bool group, TABLE *table);
void clear()
@@ -513,8 +507,7 @@ class Item_sum_percent_rank: public Item_sum_window_with_row_count
row_number= 0;
}
bool add();
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
void fix_length_and_dec()
{
@@ -599,8 +592,7 @@ class Item_sum_cume_dist: public Item_sum_window_with_row_count
}
void update_field() {}
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
void fix_length_and_dec()
{
@@ -676,8 +668,7 @@ class Item_sum_ntile : public Item_sum_window_with_row_count
void update_field() {}
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_sum_ntile>(thd, mem_root, this); }
@@ -692,12 +683,12 @@ class Item_window_func : public Item_func_or_sum
{
/* Window function parameters as we've got them from the parser */
public:
- LEX_STRING *window_name;
+ LEX_CSTRING *window_name;
public:
Window_spec *window_spec;
public:
- Item_window_func(THD *thd, Item_sum *win_func, LEX_STRING *win_name)
+ Item_window_func(THD *thd, Item_sum *win_func, LEX_CSTRING *win_name)
: Item_func_or_sum(thd, (Item *) win_func),
window_name(win_name), window_spec(NULL),
force_return_blank(true),
@@ -802,9 +793,9 @@ public:
*/
void setup_partition_border_check(THD *thd);
- enum_field_types field_type() const
- {
- return ((Item_sum *) args[0])->field_type();
+ const Type_handler *type_handler() const
+ {
+ return ((Item_sum *) args[0])->type_handler();
}
enum Item::Type type() const { return Item::WINDOW_FUNC_ITEM; }
@@ -851,7 +842,7 @@ public:
bool is_null()
{
if (force_return_blank)
- return false;
+ return true;
if (read_value_from_result_field)
return result_field->is_null();
@@ -865,7 +856,7 @@ public:
if (force_return_blank)
{
res= 0.0;
- null_value= false;
+ null_value= true;
}
else if (read_value_from_result_field)
{
@@ -886,7 +877,7 @@ public:
if (force_return_blank)
{
res= 0;
- null_value= false;
+ null_value= true;
}
else if (read_value_from_result_field)
{
@@ -906,9 +897,8 @@ public:
String *res;
if (force_return_blank)
{
- null_value= false;
- str->length(0);
- res= str;
+ null_value= true;
+ res= NULL;
}
else if (read_value_from_result_field)
{
@@ -930,9 +920,8 @@ public:
my_decimal *res;
if (force_return_blank)
{
- my_decimal_set_zero(dec);
- null_value= false;
- res= dec;
+ null_value= true;
+ res= NULL;
}
else if (read_value_from_result_field)
{
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 10dda8f20e8..ba33d103d0c 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -462,13 +462,13 @@ public:
};
-class Item_func_xpath_position :public Item_int_func
+class Item_func_xpath_position :public Item_long_func
{
String *pxml;
String tmp_value;
public:
Item_func_xpath_position(THD *thd, Item *a, String *p):
- Item_int_func(thd, a), pxml(p) {}
+ Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_position"; }
void fix_length_and_dec() { max_length=10; }
longlong val_int()
@@ -483,13 +483,13 @@ public:
};
-class Item_func_xpath_count :public Item_int_func
+class Item_func_xpath_count :public Item_long_func
{
String *pxml;
String tmp_value;
public:
Item_func_xpath_count(THD *thd, Item *a, String *p):
- Item_int_func(thd, a), pxml(p) {}
+ Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_count"; }
void fix_length_and_dec() { max_length=10; }
longlong val_int()
@@ -2595,7 +2595,7 @@ my_xpath_parse_QName(MY_XPATH *xpath)
static int
my_xpath_parse_VariableReference(MY_XPATH *xpath)
{
- LEX_STRING name;
+ LEX_CSTRING name;
int user_var;
const char *dollar_pos;
THD *thd= xpath->thd;
@@ -2610,7 +2610,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
name.str= (char*) xpath->prevtok.beg;
if (user_var)
- xpath->item= new (thd->mem_root) Item_func_get_user_var(thd, name);
+ xpath->item= new (thd->mem_root) Item_func_get_user_var(thd, &name);
else
{
sp_variable *spv;
@@ -2618,10 +2618,10 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
LEX *lex;
if ((lex= thd->lex) &&
(spc= lex->spcont) &&
- (spv= spc->find_variable(name, false)))
+ (spv= spc->find_variable(&name, false)))
{
Item_splocal *splocal= new (thd->mem_root)
- Item_splocal(thd, name, spv->offset, spv->sql_type(), 0);
+ Item_splocal(thd, &name, spv->offset, spv->sql_type(), 0);
#ifndef DBUG_OFF
if (splocal)
splocal->m_sp= lex->sphead;
diff --git a/sql/key.cc b/sql/key.cc
index 0c931184da7..c2d22005736 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -112,7 +112,7 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field,
@param with_zerofill skipped bytes in the key buffer to be filled with 0
*/
-void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
+void key_copy(uchar *to_key, const uchar *from_record, KEY *key_info,
uint key_length, bool with_zerofill)
{
uint length;
diff --git a/sql/key.h b/sql/key.h
index f2521e4a665..7b83d74c901 100644
--- a/sql/key.h
+++ b/sql/key.h
@@ -27,8 +27,8 @@ typedef struct st_key_part_info KEY_PART_INFO;
int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field,
uint *key_length, uint *keypart);
-void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, uint key_length,
- bool with_zerofill= FALSE);
+void key_copy(uchar *to_key, const uchar *from_record, KEY *key_info,
+ uint key_length, bool with_zerofill= FALSE);
void key_restore(uchar *to_record, const uchar *from_key, KEY *key_info,
uint key_length);
bool key_cmp_if_same(TABLE *form,const uchar *key,uint index,uint key_length);
diff --git a/sql/keycaches.cc b/sql/keycaches.cc
index 78e64ebac72..336f2611a7e 100644
--- a/sql/keycaches.cc
+++ b/sql/keycaches.cc
@@ -99,11 +99,11 @@ void NAMED_ILIST::delete_elements(void (*free_element)(const char *name, uchar*)
/* Key cache functions */
-LEX_STRING default_key_cache_base= {C_STRING_WITH_LEN("default")};
+LEX_CSTRING default_key_cache_base= {C_STRING_WITH_LEN("default")};
KEY_CACHE zero_key_cache; ///< @@nonexistent_cache.param->value_ptr() points here
-KEY_CACHE *get_key_cache(const LEX_STRING *cache_name)
+KEY_CACHE *get_key_cache(const LEX_CSTRING *cache_name)
{
if (!cache_name || ! cache_name->length)
cache_name= &default_key_cache_base;
@@ -145,10 +145,10 @@ KEY_CACHE *create_key_cache(const char *name, uint length)
KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
{
- LEX_STRING key_cache_name;
+ LEX_CSTRING key_cache_name;
KEY_CACHE *key_cache;
- key_cache_name.str= (char *) name;
+ key_cache_name.str= name;
key_cache_name.length= length;
if (!(key_cache= get_key_cache(&key_cache_name)))
key_cache= create_key_cache(name, length);
diff --git a/sql/keycaches.h b/sql/keycaches.h
index fff48d51c6f..1b58dccfe34 100644
--- a/sql/keycaches.h
+++ b/sql/keycaches.h
@@ -35,12 +35,12 @@ class NAMED_ILIST: public I_List<NAMED_ILINK>
};
/* For key cache */
-extern LEX_STRING default_key_cache_base;
+extern LEX_CSTRING default_key_cache_base;
extern KEY_CACHE zero_key_cache;
extern NAMED_ILIST key_caches;
KEY_CACHE *create_key_cache(const char *name, uint length);
-KEY_CACHE *get_key_cache(const LEX_STRING *cache_name);
+KEY_CACHE *get_key_cache(const LEX_CSTRING *cache_name);
KEY_CACHE *get_or_create_key_cache(const char *name, uint length);
void free_key_cache(const char *name, KEY_CACHE *key_cache);
bool process_key_caches(process_key_cache_t func, void *param);
diff --git a/sql/lex.h b/sql/lex.h
index baeae088234..f2dac95fce5 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -114,6 +114,7 @@ static SYMBOL symbols[] = {
{ "CIPHER", SYM(CIPHER_SYM)},
{ "CLASS_ORIGIN", SYM(CLASS_ORIGIN_SYM)},
{ "CLIENT", SYM(CLIENT_SYM)},
+ { "CLOB", SYM(CLOB)},
{ "CLOSE", SYM(CLOSE_SYM)},
{ "COALESCE", SYM(COALESCE)},
{ "CODE", SYM(CODE_SYM)},
@@ -159,6 +160,7 @@ static SYMBOL symbols[] = {
{ "CURRENT_USER", SYM(CURRENT_USER)},
{ "CURSOR", SYM(CURSOR_SYM)},
{ "CURSOR_NAME", SYM(CURSOR_NAME_SYM)},
+ { "CYCLE", SYM(CYCLE_SYM)},
{ "DATA", SYM(DATA_SYM)},
{ "DATABASE", SYM(DATABASE)},
{ "DATABASES", SYM(DATABASES)},
@@ -202,6 +204,7 @@ static SYMBOL symbols[] = {
{ "EACH", SYM(EACH_SYM)},
{ "ELSE", SYM(ELSE)},
{ "ELSEIF", SYM(ELSEIF_SYM)},
+ { "ELSIF", SYM(ELSIF_SYM)},
{ "ENABLE", SYM(ENABLE_SYM)},
{ "ENCLOSED", SYM(ENCLOSED)},
{ "END", SYM(END)},
@@ -217,9 +220,11 @@ static SYMBOL symbols[] = {
{ "EVENTS", SYM(EVENTS_SYM)},
{ "EVERY", SYM(EVERY_SYM)},
{ "EXAMINED", SYM(EXAMINED_SYM)},
+ { "EXCEPT", SYM(EXCEPT_SYM)},
{ "EXCHANGE", SYM(EXCHANGE_SYM)},
{ "EXCLUDE", SYM(EXCLUDE_SYM)},
{ "EXECUTE", SYM(EXECUTE_SYM)},
+ { "EXCEPTION", SYM(EXCEPTION_SYM)},
{ "EXISTS", SYM(EXISTS)},
{ "EXIT", SYM(EXIT_SYM)},
{ "EXPANSION", SYM(EXPANSION_SYM)},
@@ -257,6 +262,7 @@ static SYMBOL symbols[] = {
{ "GET_FORMAT", SYM(GET_FORMAT)},
{ "GET", SYM(GET_SYM)},
{ "GLOBAL", SYM(GLOBAL_SYM)},
+ { "GOTO", SYM(GOTO_SYM)},
{ "GRANT", SYM(GRANT)},
{ "GRANTS", SYM(GRANTS)},
{ "GROUP", SYM(GROUP_SYM)},
@@ -280,7 +286,9 @@ static SYMBOL symbols[] = {
{ "IGNORE_SERVER_IDS", SYM(IGNORE_SERVER_IDS_SYM)},
{ "IMMEDIATE", SYM(IMMEDIATE_SYM)},
{ "IMPORT", SYM(IMPORT)},
+ { "INTERSECT", SYM(INTERSECT_SYM)},
{ "IN", SYM(IN_SYM)},
+ { "INCREMENT", SYM(INCREMENT_SYM)},
{ "INDEX", SYM(INDEX_SYM)},
{ "INDEXES", SYM(INDEXES)},
{ "INFILE", SYM(INFILE)},
@@ -305,6 +313,7 @@ static SYMBOL symbols[] = {
{ "IPC", SYM(IPC_SYM)},
{ "IS", SYM(IS)},
{ "ISOLATION", SYM(ISOLATION)},
+ { "ISOPEN", SYM(ISOPEN_SYM)},
{ "ISSUER", SYM(ISSUER_SYM)},
{ "ITERATE", SYM(ITERATE_SYM)},
{ "INVOKER", SYM(INVOKER_SYM)},
@@ -317,6 +326,7 @@ static SYMBOL symbols[] = {
{ "LANGUAGE", SYM(LANGUAGE_SYM)},
{ "LAST", SYM(LAST_SYM)},
{ "LAST_VALUE", SYM(LAST_VALUE)},
+ { "LASTVAL", SYM(LASTVAL_SYM)},
{ "LEADING", SYM(LEADING)},
{ "LEAVE", SYM(LEAVE_SYM)},
{ "LEAVES", SYM(LEAVES)},
@@ -372,7 +382,7 @@ static SYMBOL symbols[] = {
{ "MAX_STATEMENT_TIME", SYM(MAX_STATEMENT_TIME_SYM)},
{ "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)},
{ "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)},
- { "MAXVALUE", SYM(MAX_VALUE_SYM)},
+ { "MAXVALUE", SYM(MAXVALUE_SYM)},
{ "MEDIUM", SYM(MEDIUM_SYM)},
{ "MEDIUMBLOB", SYM(MEDIUMBLOB)},
{ "MEDIUMINT", SYM(MEDIUMINT)},
@@ -386,6 +396,7 @@ static SYMBOL symbols[] = {
{ "MINUTE", SYM(MINUTE_SYM)},
{ "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM)},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM)},
+ { "MINVALUE", SYM(MINVALUE_SYM)},
{ "MIN_ROWS", SYM(MIN_ROWS)},
{ "MOD", SYM(MOD_SYM)},
{ "MODE", SYM(MODE_SYM)},
@@ -405,16 +416,23 @@ static SYMBOL symbols[] = {
{ "NCHAR", SYM(NCHAR_SYM)},
{ "NEW", SYM(NEW_SYM)},
{ "NEXT", SYM(NEXT_SYM)},
+ { "NEXTVAL", SYM(NEXTVAL_SYM)},
{ "NO", SYM(NO_SYM)},
+ { "NOMAXVALUE", SYM(NOMAXVALUE_SYM)},
+ { "NOMINVALUE", SYM(NOMINVALUE_SYM)},
+ { "NOCACHE", SYM(NOCACHE_SYM)},
+ { "NOCYCLE", SYM(NOCYCLE_SYM)},
{ "NO_WAIT", SYM(NO_WAIT_SYM)},
{ "NODEGROUP", SYM(NODEGROUP_SYM)},
{ "NONE", SYM(NONE_SYM)},
{ "NOT", SYM(NOT_SYM)},
+ { "NOTFOUND", SYM(NOTFOUND_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
{ "NULL", SYM(NULL_SYM)},
{ "NUMBER", SYM(NUMBER_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)},
{ "NVARCHAR", SYM(NVARCHAR_SYM)},
+ { "OF", SYM(OF_SYM)},
{ "OFFSET", SYM(OFFSET_SYM)},
{ "OLD_PASSWORD", SYM(OLD_PASSWORD_SYM)},
{ "ON", SYM(ON)},
@@ -457,6 +475,7 @@ static SYMBOL symbols[] = {
{ "PREPARE", SYM(PREPARE_SYM)},
{ "PRESERVE", SYM(PRESERVE_SYM)},
{ "PREV", SYM(PREV_SYM)},
+ { "PREVIOUS", SYM(PREVIOUS_SYM)},
{ "PRIMARY", SYM(PRIMARY_SYM)},
{ "PRIVILEGES", SYM(PRIVILEGES)},
{ "PROCEDURE", SYM(PROCEDURE_SYM)},
@@ -469,7 +488,9 @@ static SYMBOL symbols[] = {
{ "QUARTER", SYM(QUARTER_SYM)},
{ "QUERY", SYM(QUERY_SYM)},
{ "QUICK", SYM(QUICK)},
+ { "RAISE", SYM(RAISE_SYM)},
{ "RANGE", SYM(RANGE_SYM)},
+ { "RAW", SYM(RAW)},
{ "READ", SYM(READ_SYM)},
{ "READ_ONLY", SYM(READ_ONLY_SYM)},
{ "READ_WRITE", SYM(READ_WRITE_SYM)},
@@ -501,6 +522,7 @@ static SYMBOL symbols[] = {
{ "REQUIRE", SYM(REQUIRE_SYM)},
{ "RESET", SYM(RESET_SYM)},
{ "RESIGNAL", SYM(RESIGNAL_SYM)},
+ { "RESTART", SYM(RESTART_SYM)},
{ "RESTORE", SYM(RESTORE_SYM)},
{ "RESTRICT", SYM(RESTRICT)},
{ "RESUME", SYM(RESUME_SYM)},
@@ -508,6 +530,7 @@ static SYMBOL symbols[] = {
{ "RETURN", SYM(RETURN_SYM)},
{ "RETURNING", SYM(RETURNING_SYM)},
{ "RETURNS", SYM(RETURNS_SYM)},
+ { "REUSE", SYM(REUSE_SYM)},
{ "REVERSE", SYM(REVERSE_SYM)},
{ "REVOKE", SYM(REVOKE)},
{ "RIGHT", SYM(RIGHT)},
@@ -517,7 +540,9 @@ static SYMBOL symbols[] = {
{ "ROLLUP", SYM(ROLLUP_SYM)},
{ "ROUTINE", SYM(ROUTINE_SYM)},
{ "ROW", SYM(ROW_SYM)},
+ { "ROWCOUNT", SYM(ROWCOUNT_SYM)}, /* Oracle-N */
{ "ROWS", SYM(ROWS_SYM)},
+ { "ROWTYPE", SYM(ROWTYPE_SYM)},
{ "ROW_COUNT", SYM(ROW_COUNT_SYM)},
{ "ROW_FORMAT", SYM(ROW_FORMAT_SYM)},
{ "RTREE", SYM(RTREE_SYM)},
@@ -532,11 +557,13 @@ static SYMBOL symbols[] = {
{ "SELECT", SYM(SELECT_SYM)},
{ "SENSITIVE", SYM(SENSITIVE_SYM)},
{ "SEPARATOR", SYM(SEPARATOR_SYM)},
+ { "SEQUENCE", SYM(SEQUENCE_SYM)},
{ "SERIAL", SYM(SERIAL_SYM)},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM)},
{ "SESSION", SYM(SESSION_SYM)},
{ "SERVER", SYM(SERVER_SYM)},
{ "SET", SYM(SET)},
+ { "SETVAL", SYM(SETVAL_SYM)},
{ "SHARE", SYM(SHARE_SYM)},
{ "SHOW", SYM(SHOW)},
{ "SHUTDOWN", SYM(SHUTDOWN)},
@@ -658,6 +685,7 @@ static SYMBOL symbols[] = {
{ "VARBINARY", SYM(VARBINARY)},
{ "VARCHAR", SYM(VARCHAR)},
{ "VARCHARACTER", SYM(VARCHAR)},
+ { "VARCHAR2", SYM(VARCHAR2)},
{ "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)},
{ "VIA", SYM(VIA_SYM)},
@@ -698,6 +726,7 @@ static SYMBOL sql_functions[] = {
{ "CURTIME", SYM(CURTIME)},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL)},
{ "DATE_SUB", SYM(DATE_SUB_INTERVAL)},
+ { "DECODE", SYM(DECODE_SYM)},
{ "DENSE_RANK", SYM(DENSE_RANK_SYM)},
{ "EXTRACT", SYM(EXTRACT_SYM)},
{ "FIRST_VALUE", SYM(FIRST_VALUE_SYM)},
diff --git a/sql/lock.cc b/sql/lock.cc
index 06cb00fe32d..a34613fb7fe 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -261,7 +261,7 @@ static void track_table_access(THD *thd, TABLE **tables, size_t count)
if (t)
tst->add_trx_state(thd, t->reginfo.lock_type,
- t->file->has_transactions());
+ t->file->has_transaction_manager());
}
}
}
@@ -442,10 +442,10 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
This will work even if get_lock_data fails (next unlock will free all)
*/
-void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count)
+void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count, uint flag)
{
MYSQL_LOCK *sql_lock=
- get_lock_data(thd, table, count, GET_LOCK_UNLOCK | GET_LOCK_ON_THD);
+ get_lock_data(thd, table, count, GET_LOCK_UNLOCK | GET_LOCK_ON_THD | flag);
if (sql_lock)
mysql_unlock_tables(thd, sql_lock, 0);
}
@@ -542,7 +542,7 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table)
DBUG_ASSERT(table->lock_position == i);
/* Unlock the table. */
- mysql_unlock_some_tables(thd, &table, /* table count */ 1);
+ mysql_unlock_some_tables(thd, &table, /* table count */ 1, 0);
/* Decrement table_count in advance, making below expressions easier */
old_tables= --locked->table_count;
@@ -736,6 +736,7 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
@param flags One of:
- GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock
- GET_LOCK_STORE_LOCKS : Store lock info in TABLE
+ - GET_LOCK_SKIP_SEQUENCES : Ignore sequences (for temporary unlock)
*/
MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
@@ -753,7 +754,8 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
TABLE *t= table_ptr[i];
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE &&
- t->s->tmp_table != INTERNAL_TMP_TABLE)
+ t->s->tmp_table != INTERNAL_TMP_TABLE &&
+ (!(flags & GET_LOCK_SKIP_SEQUENCES) || t->s->sequence == 0))
{
lock_count+= t->file->lock_count();
table_count++;
@@ -784,7 +786,8 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
THR_LOCK_DATA **locks_start;
table= table_ptr[i];
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE ||
- table->s->tmp_table == INTERNAL_TMP_TABLE)
+ table->s->tmp_table == INTERNAL_TMP_TABLE ||
+ ((flags & GET_LOCK_SKIP_SEQUENCES) && table->s->sequence))
continue;
lock_type= table->reginfo.lock_type;
DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT);
diff --git a/sql/lock.h b/sql/lock.h
index 341d7a20f9f..35cb3043d57 100644
--- a/sql/lock.h
+++ b/sql/lock.h
@@ -31,7 +31,7 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags);
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock);
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
-void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
+void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count, uint flag);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock);
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
@@ -47,6 +47,7 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type,
#define GET_LOCK_STORE_LOCKS 1
#define GET_LOCK_ACTION_MASK 1
#define GET_LOCK_ON_THD (1 << 1)
+#define GET_LOCK_SKIP_SEQUENCES (1 << 2)
MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags);
void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock);
diff --git a/sql/log.cc b/sql/log.cc
index e2308f46ad4..166180e08a4 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -61,6 +61,8 @@
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_TIME_SIZE 32
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
+/* Truncate cache log files bigger than this */
+#define CACHE_FILE_TRUNC_SIZE 65536
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
@@ -250,7 +252,8 @@ void make_default_log_name(char **out, const char* log_ext, bool once)
class binlog_cache_data
{
public:
- binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF),
+ binlog_cache_data(): m_pending(0), status(0),
+ before_stmt_pos(MY_OFF_T_UNDEF),
incident(FALSE), changes_to_non_trans_temp_table_flag(FALSE),
saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
ptr_binlog_cache_disk_use(0)
@@ -262,9 +265,22 @@ public:
close_cached_file(&cache_log);
}
+ /*
+ Return 1 if there is no relevant entries in the cache
+
+ This is:
+ - Cache is empty
+ - There are row or critical (DDL?) events in the cache
+
+ The status test is needed to avoid writing entries with only
+ a table map entry, which would crash in do_apply_event() on the slave
+ as it assumes that there is always a row entry after a table map.
+ */
bool empty() const
{
- return pending() == NULL && my_b_tell(&cache_log) == 0;
+ return (pending() == NULL &&
+ (my_b_write_tell(&cache_log) == 0 ||
+ ((status & (LOGGED_ROW_EVENT | LOGGED_CRITICAL)) == 0)));
}
Rows_log_event *pending() const
@@ -299,23 +315,19 @@ public:
void reset()
{
- compute_statistics();
- truncate(0);
- if(cache_log.file != -1)
+ bool cache_was_empty= empty();
+ bool truncate_file= (cache_log.file != -1 &&
+ my_b_write_tell(&cache_log) > CACHE_FILE_TRUNC_SIZE);
+ truncate(0,1); // Forget what's in cache
+ if (!cache_was_empty)
+ compute_statistics();
+ if (truncate_file)
my_chsize(cache_log.file, 0, 0, MYF(MY_WME));
changes_to_non_trans_temp_table_flag= FALSE;
+ status= 0;
incident= FALSE;
before_stmt_pos= MY_OFF_T_UNDEF;
- /*
- The truncate function calls reinit_io_cache that calls
- my_b_flush_io_cache which may increase disk_writes. This breaks
- the disk_writes use by the binary log which aims to compute the
- ratio between in-memory cache usage and disk cache usage. To
- avoid this undesirable behavior, we reset the variable after
- truncating the cache.
- */
- cache_log.disk_writes= 0;
DBUG_ASSERT(empty());
}
@@ -376,6 +388,11 @@ public:
cache_log.end_of_file= saved_max_binlog_cache_size;
}
+ void add_status(enum_logged_status status_arg)
+ {
+ status|= status_arg;
+ }
+
/*
Cache to store data before copying it to the binary log.
*/
@@ -389,6 +406,13 @@ private:
Rows_log_event *m_pending;
/*
+ Bit flags for what has been writting to cache. Used to
+ discard logs without any data changes.
+ see enum_logged_status;
+ */
+ uint32 status;
+
+ /*
Binlog position before the start of the current statement.
*/
my_off_t before_stmt_pos;
@@ -410,11 +434,16 @@ private:
*/
void compute_statistics()
{
- if (!empty())
+ statistic_increment(*ptr_binlog_cache_use, &LOCK_status);
+ if (cache_log.disk_writes != 0)
{
- statistic_increment(*ptr_binlog_cache_use, &LOCK_status);
- if (cache_log.disk_writes != 0)
- statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status);
+#ifdef REAL_STATISTICS
+ statistic_add(*ptr_binlog_cache_disk_use,
+ cache_log.disk_writes, &LOCK_status);
+#else
+ statistic_increment(*ptr_binlog_cache_disk_use, &LOCK_status);
+#endif
+ cache_log.disk_writes= 0;
}
}
@@ -443,7 +472,7 @@ private:
It truncates the cache to a certain position. This includes deleting the
pending event.
*/
- void truncate(my_off_t pos)
+ void truncate(my_off_t pos, bool reset_cache=0)
{
DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
if (pending())
@@ -451,7 +480,7 @@ private:
delete pending();
set_pending(0);
}
- reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, 0);
+ reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, reset_cache);
cache_log.end_of_file= saved_max_binlog_cache_size;
}
@@ -459,6 +488,13 @@ private:
binlog_cache_data(const binlog_cache_data& info);
};
+
+void Log_event_writer::add_status(enum_logged_status status)
+{
+ if (likely(cache_data))
+ cache_data->add_status(status);
+}
+
class binlog_cache_mngr {
public:
binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size,
@@ -976,7 +1012,7 @@ int Log_to_csv_event_handler::
{
TABLE_LIST table_list;
TABLE *table;
- LEX_STRING *UNINIT_VAR(log_name);
+ LEX_CSTRING *UNINIT_VAR(log_name);
int result;
Open_tables_backup open_tables_backup;
@@ -5190,12 +5226,14 @@ end:
DBUG_RETURN(error);
}
-bool MYSQL_BIN_LOG::write_event(Log_event *ev, IO_CACHE *file)
+bool MYSQL_BIN_LOG::write_event(Log_event *ev, binlog_cache_data *cache_data,
+ IO_CACHE *file)
{
- Log_event_writer writer(file, &crypto);
+ Log_event_writer writer(file, 0, &crypto);
if (crypto.scheme && file == &log_file)
writer.ctx= alloca(crypto.ctx_size);
-
+ if (cache_data)
+ cache_data->add_status(ev->logged_status());
return writer.write(ev);
}
@@ -5632,12 +5670,10 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
-
- IO_CACHE *file=
- cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional));
- Log_event_writer writer(file);
- binlog_cache_data *cache_data=
- cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
+ binlog_cache_data *cache_data= (cache_mngr->
+ get_binlog_cache_data(is_transactional));
+ IO_CACHE *file= &cache_data->cache_log;
+ Log_event_writer writer(file, cache_data);
if (with_annotate && *with_annotate)
{
@@ -5778,7 +5814,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
if (Rows_log_event* pending= cache_data->pending())
{
- Log_event_writer writer(&cache_data->cache_log);
+ Log_event_writer writer(&cache_data->cache_log, cache_data);
/*
Write pending event to the cache.
@@ -6190,8 +6226,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
goto err;
is_trans_cache= use_trans_cache(thd, using_trans);
- file= cache_mngr->get_binlog_cache_log(is_trans_cache);
cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
+ file= &cache_data->cache_log;
if (thd->lex->stmt_accessed_non_trans_temp_table())
cache_data->set_changes_to_non_trans_temp_table();
@@ -6215,21 +6251,19 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
Annotate_rows_log_event anno(thd, using_trans, direct);
/* Annotate event should be written not more than once */
*with_annotate= 0;
- if (write_event(&anno, file))
+ if (write_event(&anno, cache_data, file))
goto err;
}
- if (thd)
{
if (!thd->is_current_stmt_binlog_format_row())
{
-
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
{
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
thd->first_successful_insert_id_in_prev_stmt_for_binlog,
using_trans, direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
@@ -6240,14 +6274,14 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
thd->auto_inc_intervals_in_cur_stmt_for_binlog.
minimum(), using_trans, direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
if (thd->rand_used)
{
Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2,
using_trans, direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
if (thd->user_var_events.elements)
@@ -6271,7 +6305,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
flags,
using_trans,
direct);
- if (write_event(&e, file))
+ if (write_event(&e, cache_data, file))
goto err;
}
}
@@ -6281,7 +6315,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
/*
Write the event.
*/
- if (write_event(event_info, file) ||
+ if (write_event(event_info, cache_data, file) ||
DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0))
goto err;
@@ -6666,7 +6700,8 @@ public:
CacheWriter(THD *thd_arg, IO_CACHE *file_arg, bool do_checksum,
Binlog_crypt_data *cr)
- : Log_event_writer(file_arg, cr), remains(0), thd(thd_arg), first(true)
+ : Log_event_writer(file_arg, 0, cr), remains(0), thd(thd_arg),
+ first(true)
{ checksum_len= do_checksum ? BINLOG_CHECKSUM_LEN : 0; }
~CacheWriter()
@@ -6674,6 +6709,7 @@ public:
int write(uchar* pos, size_t len)
{
+ DBUG_ENTER("CacheWriter::write");
if (first)
write_header(pos, len);
else
@@ -6682,7 +6718,7 @@ public:
remains -= len;
if ((first= !remains))
write_footer();
- return 0;
+ DBUG_RETURN(0);
}
private:
THD *thd;
diff --git a/sql/log.h b/sql/log.h
index 4471f0be26d..eaa63d4072d 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -415,8 +415,10 @@ private:
( ((ulong)(c)>>1) == BINLOG_COOKIE_DUMMY_ID )
class binlog_cache_mngr;
+class binlog_cache_data;
struct rpl_gtid;
struct wait_for_commit;
+
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
{
private:
@@ -743,8 +745,8 @@ public:
void stop_union_events(THD *thd);
bool is_query_in_union(THD *thd, query_id_t query_id_param);
- bool write_event(Log_event *ev, IO_CACHE *file);
- bool write_event(Log_event *ev) { return write_event(ev, &log_file); }
+ bool write_event(Log_event *ev, binlog_cache_data *data, IO_CACHE *file);
+ bool write_event(Log_event *ev) { return write_event(ev, 0, &log_file); }
bool write_event_buffer(uchar* buf,uint len);
bool append(Log_event* ev);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 26c288ef767..8f2a61f12a4 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -587,7 +587,7 @@ pretty_print_str(String *packet, const char *str, int len)
*/
static char *load_data_tmp_prefix(char *name,
- LEX_STRING *connection_name)
+ LEX_CSTRING *connection_name)
{
name= strmov(name, PREFIX_SQL_LOAD);
if (connection_name->length)
@@ -623,7 +623,7 @@ static char *load_data_tmp_prefix(char *name,
static char *slave_load_file_stem(char *buf, uint file_id,
int event_server_id, const char *ext,
- LEX_STRING *connection_name)
+ LEX_CSTRING *connection_name)
{
char *res;
res= buf+ unpack_dirname(buf, slave_load_tmpdir);
@@ -644,7 +644,7 @@ static char *slave_load_file_stem(char *buf, uint file_id,
Delete all temporary files used for SQL_LOAD.
*/
-static void cleanup_load_tmpdir(LEX_STRING *connection_name)
+static void cleanup_load_tmpdir(LEX_CSTRING *connection_name)
{
MY_DIR *dirp;
FILEINFO *file;
@@ -3823,8 +3823,8 @@ bool Query_log_event::write()
if (thd && thd->need_binlog_invoker())
{
- LEX_STRING user;
- LEX_STRING host;
+ LEX_CSTRING user;
+ LEX_CSTRING host;
memset(&user, 0, sizeof(user));
memset(&host, 0, sizeof(host));
@@ -3847,7 +3847,7 @@ bool Query_log_event::write()
else
{
user.str= ctx->priv_role;
- host= empty_lex_str;
+ host= empty_clex_str;
}
user.length= strlen(user.str);
}
@@ -4077,10 +4077,12 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
switch (lex->sql_command)
{
case SQLCOM_DROP_TABLE:
+ case SQLCOM_DROP_SEQUENCE:
use_cache= (lex->tmp_table() && thd->in_multi_stmt_transaction_mode());
break;
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
/*
If we are using CREATE ... SELECT or if we are a slave
executing BEGIN...COMMIT (generated by CREATE...SELECT) we
@@ -4499,22 +4501,20 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
if (user.length)
{
- copy_str_and_move((const char **)&(user.str), &start, user.length);
+ copy_str_and_move(&user.str, &start, user.length);
}
else
{
- user.str= (char *) start++;
- user.str[0]= '\0';
+ user.str= (char*) start;
+ *(start++)= 0;
}
if (host.length)
- {
- copy_str_and_move((const char **)&(host.str), &start, host.length);
- }
+ copy_str_and_move(&host.str, &start, host.length);
else
{
- host.str= (char *) start++;
- host.str[0]= '\0';
+ host.str= (char*) start;
+ *(start++)= 0;
}
/**
@@ -5320,7 +5320,8 @@ compare_errors:
has already been dropped. To ignore such irrelevant "table does
not exist errors", we silently clear the error if TEMPORARY was used.
*/
- if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
+ if ((thd->lex->sql_command == SQLCOM_DROP_TABLE ||
+ thd->lex->sql_command == SQLCOM_DROP_SEQUENCE) &&
thd->lex->tmp_table() &&
thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_BAD_TABLE_ERROR &&
!expected_error)
@@ -6558,9 +6559,9 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
while ((item = li++))
{
num_fields++;
- uchar len = (uchar) strlen(item->name);
+ uchar len= (uchar) item->name.length;
field_block_len += len + 1;
- fields_buf.append(item->name, len + 1);
+ fields_buf.append(item->name.str, len + 1);
field_lens_buf.append((char*)&len, 1);
}
@@ -6786,9 +6787,10 @@ void Load_log_event::set_fields(const char* affected_db,
const char* field = fields;
for (i= 0; i < num_fields; i++)
{
+ LEX_CSTRING field_name= {field, field_lens[i] };
field_list.push_back(new (thd->mem_root)
Item_field(thd, context, affected_db, table_name,
- field),
+ &field_name),
thd->mem_root);
field+= field_lens[i] + 1;
}
@@ -8911,7 +8913,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
DBUG_RETURN(1);
- LEX_STRING user_var_name;
+ LEX_CSTRING user_var_name;
user_var_name.str= name;
user_var_name.length= name_len;
double real_val;
@@ -8954,7 +8956,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
}
}
- Item_func_set_user_var *e= new (thd->mem_root) Item_func_set_user_var(thd, user_var_name, it);
+ Item_func_set_user_var *e= new (thd->mem_root) Item_func_set_user_var(thd, &user_var_name, it);
/*
Item_func_set_user_var can't substitute something else on its place =>
0 can be passed as last argument (reference on item)
@@ -8971,7 +8973,7 @@ int User_var_log_event::do_apply_event(rpl_group_info *rgi)
a single record and with a single column. Thus, like
a column value, it could always have IMPLICIT derivation.
*/
- e->update_hash(val, val_len, type, charset,
+ e->update_hash((void*) val, val_len, type, charset,
(flags & User_var_log_event::UNSIGNED_F));
if (!is_deferred())
free_root(thd->mem_root, 0);
@@ -9300,7 +9302,7 @@ int Create_file_log_event::do_apply_event(rpl_group_info *rgi)
char *ext;
int fd = -1;
IO_CACHE file;
- Log_event_writer lew(&file);
+ Log_event_writer lew(&file, 0);
int error = 1;
Relay_log_info const *rli= rgi->rli;
@@ -11331,7 +11333,9 @@ Annotate_rows_log_event::Annotate_rows_log_event(THD *thd,
bool direct)
: Log_event(thd, 0, using_trans),
m_save_thd_query_txt(0),
- m_save_thd_query_len(0), m_saved_thd_query(false)
+ m_save_thd_query_len(0),
+ m_saved_thd_query(false),
+ m_used_query_txt(0)
{
m_query_txt= thd->query();
m_query_len= thd->query_length();
@@ -11345,7 +11349,9 @@ Annotate_rows_log_event::Annotate_rows_log_event(const char *buf,
const Format_description_log_event *desc)
: Log_event(buf, desc),
m_save_thd_query_txt(0),
- m_save_thd_query_len(0), m_saved_thd_query(false)
+ m_save_thd_query_len(0),
+ m_saved_thd_query(false),
+ m_used_query_txt(0)
{
m_query_len= event_len - desc->common_header_len;
m_query_txt= (char*) buf + desc->common_header_len;
@@ -11353,10 +11359,14 @@ Annotate_rows_log_event::Annotate_rows_log_event(const char *buf,
Annotate_rows_log_event::~Annotate_rows_log_event()
{
+ DBUG_ENTER("Annotate_rows_log_event::~Annotate_rows_log_event");
#ifndef MYSQL_CLIENT
if (m_saved_thd_query)
thd->set_query(m_save_thd_query_txt, m_save_thd_query_len);
+ else if (m_used_query_txt)
+ thd->reset_query();
#endif
+ DBUG_VOID_RETURN;
}
int Annotate_rows_log_event::get_data_size()
@@ -11442,6 +11452,7 @@ int Annotate_rows_log_event::do_apply_event(rpl_group_info *rgi)
m_save_thd_query_txt= thd->query();
m_save_thd_query_len= thd->query_length();
m_saved_thd_query= true;
+ m_used_query_txt= 1;
thd->set_query(m_query_txt, m_query_len);
return 0;
}
@@ -11993,7 +12004,7 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi)
table_list->table_id= DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id);
table_list->updating= 1;
- table_list->required_type= FRMTYPE_TABLE;
+ table_list->required_type= TABLE_TYPE_NORMAL;
DBUG_PRINT("debug", ("table: %s is mapped to %u", table_list->table_name,
table_list->table_id));
@@ -12518,7 +12529,9 @@ Rows_log_event::write_row(rpl_group_info *rgi,
TODO: Add safety measures against infinite looping.
*/
- while ((error= table->file->ha_write_row(table->record[0])))
+ if (table->s->sequence)
+ error= update_sequence();
+ else while ((error= table->file->ha_write_row(table->record[0])))
{
if (error == HA_ERR_LOCK_DEADLOCK ||
error == HA_ERR_LOCK_WAIT_TIMEOUT ||
@@ -12685,6 +12698,33 @@ Rows_log_event::write_row(rpl_group_info *rgi,
DBUG_RETURN(error);
}
+
+int Rows_log_event::update_sequence()
+{
+ TABLE *table= m_table; // pointer to event's table
+
+ if (!bitmap_is_set(table->rpl_write_set, MIN_VALUE_FIELD_NO))
+ {
+ /* This event come from a setval function executed on the master.
+ Update the sequence next_number and round, like we do with setval()
+ */
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
+ table->read_set);
+ longlong nextval= table->field[NEXT_FIELD_NO]->val_int();
+ longlong round= table->field[ROUND_FIELD_NO]->val_int();
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+
+ return table->s->sequence->set_value(table, nextval, round, 0);
+ }
+
+ /*
+ Update all fields in table and update the active sequence, like with
+ ALTER SEQUENCE
+ */
+ return table->file->ha_write_row(table->record[0]);
+}
+
+
#endif
int
diff --git a/sql/log_event.h b/sql/log_event.h
index a06781aebeb..6f71784cfea 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -716,6 +716,21 @@ enum Log_event_type
ENUM_END_EVENT /* end marker */
};
+
+/*
+ Bit flags for what has been writting to cache. Used to
+ discard logs with table map events but not row events and
+ nothing else important. This is stored by cache.
+*/
+
+enum enum_logged_status
+{
+ LOGGED_TABLE_MAP= 1,
+ LOGGED_ROW_EVENT= 2,
+ LOGGED_NO_DATA= 4,
+ LOGGED_CRITICAL= 8
+};
+
static inline bool LOG_EVENT_IS_QUERY(enum Log_event_type type)
{
return type == QUERY_EVENT || type == QUERY_COMPRESSED_EVENT;
@@ -785,6 +800,7 @@ class THD;
class Format_description_log_event;
class Relay_log_info;
+class binlog_cache_data;
#ifdef MYSQL_CLIENT
enum enum_base64_output_mode {
@@ -896,6 +912,7 @@ typedef struct st_print_event_info
This class encapsulates writing of Log_event objects to IO_CACHE.
Automatically calculates the checksum and encrypts the data, if necessary.
*/
+
class Log_event_writer
{
public:
@@ -907,13 +924,16 @@ public:
int write_data(const uchar *pos, size_t len);
int write_footer();
my_off_t pos() { return my_b_safe_tell(file); }
+ void add_status(enum_logged_status status);
-Log_event_writer(IO_CACHE *file_arg, Binlog_crypt_data *cr= 0)
+ Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg,
+ Binlog_crypt_data *cr= 0)
: bytes_written(0), ctx(0),
- file(file_arg), crypto(cr) { }
+ file(file_arg), cache_data(cache_data_arg), crypto(cr) { }
private:
IO_CACHE *file;
+ binlog_cache_data *cache_data;
/**
Placeholder for event checksum while writing to binlog.
*/
@@ -1236,7 +1256,7 @@ public:
bool is_more);
void print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info,
bool is_more);
-#endif
+#endif /* MYSQL_SERVER */
/* The following code used for Flashback */
#ifdef MYSQL_CLIENT
@@ -1382,6 +1402,7 @@ public:
}
#endif
virtual Log_event_type get_type_code() = 0;
+ virtual enum_logged_status logged_status() { return LOGGED_CRITICAL; }
virtual bool is_valid() const = 0;
virtual my_off_t get_header_len(my_off_t len) { return len; }
void set_artificial_event() { flags |= LOG_EVENT_ARTIFICIAL_F; }
@@ -1992,8 +2013,8 @@ protected:
*/
class Query_log_event: public Log_event
{
- LEX_STRING user;
- LEX_STRING host;
+ LEX_CSTRING user;
+ LEX_CSTRING host;
protected:
Log_event::Byte* data_buf;
public:
@@ -3020,9 +3041,9 @@ public:
UNDEF_F= 0,
UNSIGNED_F= 1
};
- char *name;
+ const char *name;
uint name_len;
- char *val;
+ const char *val;
ulong val_len;
Item_result type;
uint charset_number;
@@ -3031,8 +3052,8 @@ public:
#ifdef MYSQL_SERVER
bool deferred;
query_id_t query_id;
- User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
- char *val_arg, ulong val_len_arg, Item_result type_arg,
+ User_var_log_event(THD* thd_arg, const char *name_arg, uint name_len_arg,
+ const char *val_arg, ulong val_len_arg, Item_result type_arg,
uint charset_number_arg, uchar flags_arg,
bool using_trans, bool direct)
:Log_event(thd_arg, 0, using_trans),
@@ -3361,6 +3382,7 @@ public:
const Format_description_log_event *description_event);
~Gtid_log_event() { }
Log_event_type get_type_code() { return GTID_EVENT; }
+ enum_logged_status logged_status() { return LOGGED_NO_DATA; }
int get_data_size()
{
return GTID_HEADER_LEN + ((flags2 & FL_GROUP_COMMIT_ID) ? 2 : 0);
@@ -3437,7 +3459,7 @@ public:
The three elements in the body repeat COUNT times to form the GTID list.
- At the time of writing, only one flag bit is in use.
+ At the time of writing, only two flag bit are in use.
Bit 28 of `count' is used for flag FLAG_UNTIL_REACHED, which is sent in a
Gtid_list event from the master to the slave to indicate that the START
@@ -3455,9 +3477,12 @@ public:
uint64 *sub_id_list;
static const uint element_size= 4+4+8;
- static const uint32 FLAG_UNTIL_REACHED= (1<<28);
- static const uint32 FLAG_IGN_GTIDS= (1<<29);
-
+ /* Upper bits stored in 'count'. See comment above */
+ enum gtid_flags
+ {
+ FLAG_UNTIL_REACHED= (1<<28),
+ FLAG_IGN_GTIDS= (1<<29),
+ };
#ifdef MYSQL_SERVER
Gtid_list_log_event(rpl_binlog_state *gtid_set, uint32 gl_flags);
Gtid_list_log_event(slave_connection_state *gtid_set, uint32 gl_flags);
@@ -3857,6 +3882,7 @@ public:
virtual int get_data_size();
virtual Log_event_type get_type_code();
+ enum_logged_status logged_status() { return LOGGED_NO_DATA; }
virtual bool is_valid() const;
virtual bool is_part_of_group() { return 1; }
@@ -3886,6 +3912,7 @@ private:
char *m_save_thd_query_txt;
uint m_save_thd_query_len;
bool m_saved_thd_query;
+ bool m_used_query_txt;
};
/**
@@ -4272,6 +4299,7 @@ public:
const char *get_db_name() const { return m_dbnam; }
virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; }
+ virtual enum_logged_status logged_status() { return LOGGED_TABLE_MAP; }
virtual bool is_valid() const { return m_memory != NULL; /* we check malloc */ }
virtual bool is_part_of_group() { return 1; }
@@ -4400,6 +4428,7 @@ public:
void update_flags() { int2store(temp_buf + m_flags_pos, m_flags); }
Log_event_type get_type_code() { return m_type; } /* Specific type (_V1 etc) */
+ enum_logged_status logged_status() { return LOGGED_ROW_EVENT; }
virtual Log_event_type get_general_type_code() = 0; /* General rows op type, no version */
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
@@ -4579,6 +4608,7 @@ protected:
int find_key(); // Find a best key to use in find_row()
int find_row(rpl_group_info *);
int write_row(rpl_group_info *, const bool);
+ int update_sequence();
// Unpack the current row into m_table->record[0], but with
// a different columns bitmap.
@@ -5163,6 +5193,7 @@ inline int Log_event_writer::write(Log_event *ev)
ev->writer= this;
int res= ev->write();
IF_DBUG(ev->writer= 0,); // writer must be set before every Log_event::write
+ add_status(ev->logged_status());
return res;
}
diff --git a/sql/mdl.cc b/sql/mdl.cc
index 25809c3d9cc..f751a8e298e 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -2320,13 +2320,6 @@ MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
if (mdl_ticket->has_stronger_or_equal_type(new_type))
DBUG_RETURN(FALSE);
- /* Only allow upgrades from UPGRADABLE/NO_WRITE/NO_READ_WRITE/READ/WRITE */
- DBUG_ASSERT(mdl_ticket->m_type == MDL_SHARED_UPGRADABLE ||
- mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
- mdl_ticket->m_type == MDL_SHARED_NO_READ_WRITE ||
- mdl_ticket->m_type == MDL_SHARED_READ ||
- mdl_ticket->m_type == MDL_SHARED_WRITE);
-
mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type,
MDL_TRANSACTION);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 592cf53b5b5..eb7bf088442 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -302,6 +302,7 @@ static TYPELIB tc_heuristic_recover_typelib=
const char *first_keyword= "first", *binary_keyword= "BINARY";
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
+const char *quoted_string= "%`s";
bool opt_large_files= sizeof(my_off_t) > 4;
static my_bool opt_autocommit; ///< for --autocommit command-line option
@@ -311,14 +312,6 @@ static my_bool opt_autocommit; ///< for --autocommit command-line option
*/
static my_bool opt_verbose= 0;
-arg_cmp_func Arg_comparator::comparator_matrix[6][2] =
-{{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
- {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
- {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
- {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row},
- {&Arg_comparator::compare_decimal, &Arg_comparator::compare_e_decimal},
- {&Arg_comparator::compare_datetime, &Arg_comparator::compare_e_datetime}};
-
/* Timer info to be used by the SQL layer */
MY_TIMER_INFO sys_timer_info;
@@ -644,10 +637,10 @@ my_bool encrypt_binlog;
my_bool encrypt_tmp_disk_tables, encrypt_tmp_files;
/** name of reference on left expression in rewritten IN subquery */
-const char *in_left_expr_name= "<left expr>";
+const LEX_CSTRING in_left_expr_name= {STRING_WITH_LEN("<left expr>") };
/** name of additional condition */
-const char *in_additional_cond= "<IN COND>";
-const char *in_having_cond= "<IN HAVING>";
+const LEX_CSTRING in_having_cond= {STRING_WITH_LEN("<IN HAVING>") };
+const LEX_CSTRING in_additional_cond= {STRING_WITH_LEN("<IN COND>") };
/** Number of connection errors when selecting on the listening port */
ulong connection_errors_select= 0;
@@ -1026,7 +1019,9 @@ static PSI_mutex_info all_server_mutexes[]=
PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
- key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock;
+ key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
+ key_LOCK_SEQUENCE;
+
static PSI_rwlock_info all_server_rwlocks[]=
{
@@ -1037,6 +1032,7 @@ static PSI_rwlock_info all_server_rwlocks[]=
{ &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0},
{ &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL},
{ &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL},
+ { &key_LOCK_SEQUENCE, "LOCK_SEQUENCE", 0},
{ &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
{ &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0}
};
@@ -2241,6 +2237,7 @@ void clean_up(bool print_message)
#endif
wsrep_thr_deinit();
my_uuid_end();
+ delete type_handler_data;
delete binlog_filter;
delete global_rpl_filter;
end_ssl();
@@ -3781,6 +3778,7 @@ SHOW_VAR com_status_vars[]= {
{"alter_function", STMT_STATUS(SQLCOM_ALTER_FUNCTION)},
{"alter_procedure", STMT_STATUS(SQLCOM_ALTER_PROCEDURE)},
{"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)},
+ {"alter_sequence", STMT_STATUS(SQLCOM_ALTER_SEQUENCE)},
{"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)},
{"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)},
{"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)},
@@ -3801,6 +3799,7 @@ SHOW_VAR com_status_vars[]= {
{"create_index", STMT_STATUS(SQLCOM_CREATE_INDEX)},
{"create_procedure", STMT_STATUS(SQLCOM_CREATE_PROCEDURE)},
{"create_role", STMT_STATUS(SQLCOM_CREATE_ROLE)},
+ {"create_sequence", STMT_STATUS(SQLCOM_CREATE_SEQUENCE)},
{"create_server", STMT_STATUS(SQLCOM_CREATE_SERVER)},
{"create_table", STMT_STATUS(SQLCOM_CREATE_TABLE)},
{"create_temporary_table", COM_STATUS(com_create_tmp_table)},
@@ -3819,6 +3818,7 @@ SHOW_VAR com_status_vars[]= {
{"drop_procedure", STMT_STATUS(SQLCOM_DROP_PROCEDURE)},
{"drop_role", STMT_STATUS(SQLCOM_DROP_ROLE)},
{"drop_server", STMT_STATUS(SQLCOM_DROP_SERVER)},
+ {"drop_sequence", STMT_STATUS(SQLCOM_DROP_SEQUENCE)},
{"drop_table", STMT_STATUS(SQLCOM_DROP_TABLE)},
{"drop_temporary_table", COM_STATUS(com_drop_tmp_table)},
{"drop_trigger", STMT_STATUS(SQLCOM_DROP_TRIGGER)},
@@ -4132,6 +4132,13 @@ static int init_common_variables()
sf_malloc_dbug_id= mariadb_dbug_id;
#endif
+ if (!(type_handler_data= new Type_handler_data) ||
+ type_handler_data->init())
+ {
+ sql_perror("Could not allocate type_handler_data");
+ return 1;
+ }
+
max_system_variables.pseudo_thread_id= ~(my_thread_id) 0;
server_start_time= flush_status_time= my_time(0);
my_disable_copystat_in_redel= 1;
@@ -4898,7 +4905,7 @@ static int init_default_storage_engine_impl(const char *opt_name,
return 0;
}
- LEX_STRING name= { engine_name, strlen(engine_name) };
+ LEX_CSTRING name= { engine_name, strlen(engine_name) };
plugin_ref plugin;
handlerton *hton;
if ((plugin= ha_resolve_by_name(0, &name, false)))
@@ -5337,7 +5344,7 @@ static int init_server_components()
else
{
/* fall back to the log files if tables are not present */
- LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
+ LEX_CSTRING csv_name={STRING_WITH_LEN("csv")};
if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
{
/* purecov: begin inspected */
@@ -7296,13 +7303,6 @@ struct my_option my_long_options[]=
&max_binlog_dump_events, &max_binlog_dump_events, 0,
GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_REPLICATION */
-#ifdef SAFE_MUTEX
- {"debug-mutex-deadlock-detector", 0,
- "Enable checking of wrong mutex usage.",
- &safe_mutex_deadlock_detector,
- &safe_mutex_deadlock_detector,
- 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
-#endif
{"debug-no-sync", 0,
"Disables system sync calls. Only for running tests or debugging!",
&my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -8425,6 +8425,7 @@ SHOW_VAR status_vars[]= {
{"Handler_rollback", (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
{"Handler_savepoint", (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
{"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
+ {"Handler_tmp_delete", (char*) offsetof(STATUS_VAR, ha_tmp_delete_count), SHOW_LONG_STATUS},
{"Handler_tmp_update", (char*) offsetof(STATUS_VAR, ha_tmp_update_count), SHOW_LONG_STATUS},
{"Handler_tmp_write", (char*) offsetof(STATUS_VAR, ha_tmp_write_count), SHOW_LONG_STATUS},
{"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
diff --git a/sql/mysqld.h b/sql/mysqld.h
index c1f4cac9956..38e42dd61f1 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -237,7 +237,7 @@ extern const char *first_keyword, *delayed_user, *binary_keyword;
extern MYSQL_PLUGIN_IMPORT const char *my_localhost;
extern MYSQL_PLUGIN_IMPORT const char **errmesg; /* Error messages */
extern const char *myisam_recover_options_str;
-extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
+extern const LEX_CSTRING in_left_expr_name, in_additional_cond, in_having_cond;
extern SHOW_VAR status_vars[];
extern struct system_variables max_system_variables;
extern struct system_status_var global_status_var;
@@ -270,6 +270,7 @@ extern my_bool encrypt_binlog;
extern my_bool encrypt_tmp_disk_tables, encrypt_tmp_files;
extern ulong encryption_algorithm;
extern const char *encryption_algorithm_names[];
+extern const char *quoted_string;
#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
@@ -313,8 +314,8 @@ extern PSI_mutex_key key_LOCK_gtid_waiting;
extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
- key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock;
-
+ key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
+ key_LOCK_SEQUENCE;
#ifdef HAVE_MMAP
extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
#endif /* HAVE_MMAP */
@@ -692,11 +693,13 @@ enum enum_query_type
QT_ITEM_CACHE_WRAPPER_SKIP_DETAILS |
QT_ITEM_SUBSELECT_ID_ONLY,
- /// This is used for EXPLAIN EXTENDED extra warnings
+ QT_SHOW_SELECT_NUMBER= (1<<10),
+ /// This is used for EXPLAIN EXTENDED extra warnings / Be more detailed
/// Be more detailed than QT_EXPLAIN.
/// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE
/// here, as it would give better readable results
- QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET,
+ QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET|
+ QT_SHOW_SELECT_NUMBER,
// If an expression is constant, print the expression, not the value
// it evaluates to. Should be used for error messages, so that they
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index ec59c0acf86..9161dee7836 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -4398,7 +4398,7 @@ static void print_partitioning_index(KEY_PART *parts, KEY_PART *parts_end)
fprintf(DBUG_FILE, "partitioning INDEX(");
for (KEY_PART *p=parts; p != parts_end; p++)
{
- fprintf(DBUG_FILE, "%s%s", p==parts?"":" ,", p->field->field_name);
+ fprintf(DBUG_FILE, "%s%s", p==parts?"":" ,", p->field->field_name.str);
}
fputs(");\n", DBUG_FILE);
DBUG_UNLOCK_FILE;
@@ -4437,7 +4437,7 @@ static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part)
fputs(" <= ", DBUG_FILE);
}
- fprintf(DBUG_FILE, "%s", part->field->field_name);
+ fprintf(DBUG_FILE, "%s", part->field->field_name.str);
if (!(arg->max_flag & NO_MAX_RANGE))
{
@@ -4476,7 +4476,7 @@ static void dbug_print_singlepoint_range(SEL_ARG **start, uint num)
for (SEL_ARG **arg= start; arg != end; arg++)
{
Field *field= (*arg)->field;
- fprintf(DBUG_FILE, "%s%s=", (arg==start)?"":", ", field->field_name);
+ fprintf(DBUG_FILE, "%s%s=", (arg==start)?"":", ", field->field_name.str);
dbug_print_field(field);
}
fputs("\n", DBUG_FILE);
@@ -7279,9 +7279,19 @@ SEL_TREE *Item_func_in::get_func_row_mm_tree(RANGE_OPT_PARAM *param,
param->current_table);
uint row_cols= key_row->cols();
Dynamic_array <Key_col_info> key_cols_info(row_cols);
- cmp_item_row *row_cmp_item= (cmp_item_row *)
- (array ? ((in_row *) array)->get_cmp_item() :
- cmp_items[(uint) ROW_RESULT]);
+ cmp_item_row *row_cmp_item;
+
+ if (array)
+ {
+ in_row *row= static_cast<in_row*>(array);
+ row_cmp_item= static_cast<cmp_item_row*>(row->get_cmp_item());
+ }
+ else
+ {
+ DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row);
+ row_cmp_item= static_cast<cmp_item_row*>(get_comparator_cmp_item(0));
+ }
+ DBUG_ASSERT(row_cmp_item);
Item **key_col_ptr= key_row->addr(0);
for(uint i= 0; i < row_cols; i++, key_col_ptr++)
@@ -7494,6 +7504,8 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param,
param->current_table);
#ifdef HAVE_SPATIAL
Field::geometry_type sav_geom_type;
+ LINT_INIT_STRUCT(sav_geom_type);
+
if (field_item->field->type() == MYSQL_TYPE_GEOMETRY)
{
sav_geom_type= ((Field_geom*) field_item->field)->geom_type;
@@ -7919,7 +7931,9 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param,
if (!(res= value->val_str(&tmp)))
DBUG_RETURN(&null_element);
- if (field->cmp_type() != STRING_RESULT)
+ if (field->cmp_type() != STRING_RESULT ||
+ field->type_handler() == &type_handler_enum ||
+ field->type_handler() == &type_handler_set)
DBUG_RETURN(0);
/*
@@ -8015,27 +8029,59 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
goto end;
err= value->save_in_field_no_warnings(field, 1);
- if (err == 2 && field->cmp_type() == STRING_RESULT)
+ if (err > 0)
{
- if (type == EQ_FUNC || type == EQUAL_FUNC)
+ if (field->type_handler() == &type_handler_enum ||
+ field->type_handler() == &type_handler_set)
{
- tree= new (alloc) SEL_ARG(field, 0, 0);
- tree->type= SEL_ARG::IMPOSSIBLE;
+ if (type == EQ_FUNC || type == EQUAL_FUNC)
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
+ goto end;
}
- else
- tree= NULL; /* Cannot infer anything */
- goto end;
- }
- if (err > 0)
- {
- if (field->cmp_type() != value->result_type())
+
+ if (err == 2 && field->cmp_type() == STRING_RESULT)
+ {
+ if (type == EQ_FUNC || type == EQUAL_FUNC)
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
+ else
+ tree= NULL; /* Cannot infer anything */
+ goto end;
+ }
+
+ if (err == 3 && field->type() == FIELD_TYPE_DATE)
+ {
+ /*
+ We were saving DATETIME into a DATE column, the conversion went ok
+ but a non-zero time part was cut off.
+
+ In MySQL's SQL dialect, DATE and DATETIME are compared as datetime
+ values. Index over a DATE column uses DATE comparison. Changing
+ from one comparison to the other is possible:
+
+ datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10'
+ datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10'
+
+ datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10'
+ datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10'
+
+ but we'll need to convert '>' to '>=' and '<' to '<='. This will
+ be done together with other types at the end of this function
+ (grep for stored_field_cmp_to_item)
+ */
+ if (type == EQ_FUNC || type == EQUAL_FUNC)
+ {
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
+ goto end;
+ }
+ // Continue with processing non-equality ranges
+ }
+ else if (field->cmp_type() != value->result_type())
{
if ((type == EQ_FUNC || type == EQUAL_FUNC) &&
value->result_type() == item_cmp_type(field->result_type(),
value->result_type()))
{
- tree= new (alloc) SEL_ARG(field, 0, 0);
- tree->type= SEL_ARG::IMPOSSIBLE;
+ tree= new (alloc) SEL_ARG_IMPOSSIBLE(field);
goto end;
}
else
@@ -8045,31 +8091,7 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
for the cases like int_field > 999999999999999999999999 as well.
*/
tree= 0;
- if (err == 3 && field->type() == FIELD_TYPE_DATE &&
- (type == GT_FUNC || type == GE_FUNC ||
- type == LT_FUNC || type == LE_FUNC) )
- {
- /*
- We were saving DATETIME into a DATE column, the conversion went ok
- but a non-zero time part was cut off.
-
- In MySQL's SQL dialect, DATE and DATETIME are compared as datetime
- values. Index over a DATE column uses DATE comparison. Changing
- from one comparison to the other is possible:
-
- datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10'
- datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10'
-
- datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10'
- datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10'
-
- but we'll need to convert '>' to '>=' and '<' to '<='. This will
- be done together with other types at the end of this function
- (grep for stored_field_cmp_to_item)
- */
- }
- else
- goto end;
+ goto end;
}
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index c1f7079ce7f..95e231433d2 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -594,6 +594,17 @@ public:
};
+class SEL_ARG_IMPOSSIBLE: public SEL_ARG
+{
+public:
+ SEL_ARG_IMPOSSIBLE(Field *field)
+ :SEL_ARG(field, 0, 0)
+ {
+ type= SEL_ARG::IMPOSSIBLE;
+ }
+};
+
+
class RANGE_OPT_PARAM
{
public:
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index f37db88957a..4024ae26b8b 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -843,34 +843,9 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM &&
inner->real_item()->type() == Item::FIELD_ITEM);
total_key_length += inner->max_length;
- if (outer->cmp_type() != inner->cmp_type())
+ if (!inner->type_handler()->subquery_type_allows_materialization(inner,
+ outer))
DBUG_RETURN(FALSE);
- switch (outer->cmp_type()) {
- case STRING_RESULT:
- if (!(outer->collation.collation == inner->collation.collation))
- DBUG_RETURN(FALSE);
- // Materialization does not work with BLOB columns
- if (inner->field_type() == MYSQL_TYPE_BLOB ||
- inner->field_type() == MYSQL_TYPE_GEOMETRY)
- DBUG_RETURN(FALSE);
- /*
- Materialization also is unable to work when create_tmp_table() will
- create a blob column because item->max_length is too big.
- The following check is copied from Item::make_string_field():
- */
- if (inner->too_big_for_varchar())
- {
- DBUG_RETURN(FALSE);
- }
- break;
- case TIME_RESULT:
- if (mysql_type_to_time_type(outer->field_type()) !=
- mysql_type_to_time_type(inner->field_type()))
- DBUG_RETURN(FALSE);
- default:
- /* suitable for materialization */
- break;
- }
}
/*
@@ -4126,12 +4101,13 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
/* Create the field */
{
+ LEX_CSTRING field_name= {STRING_WITH_LEN("rowids") };
/*
For the sake of uniformity, always use Field_varstring (altough we could
use Field_string for shorter keys)
*/
- field= new Field_varstring(uniq_tuple_length_arg, FALSE, "rowids", share,
- &my_charset_bin);
+ field= new Field_varstring(uniq_tuple_length_arg, FALSE, &field_name,
+ share, &my_charset_bin);
if (!field)
DBUG_RETURN(0);
field->table= table;
@@ -4995,13 +4971,13 @@ int rewrite_to_index_subquery_engine(JOIN *join)
join->unit->item &&
join->unit->item->substype() == Item_subselect::IN_SUBS &&
join->table_count == 1 && join->conds &&
- !join->unit->is_union())
+ !join->unit->is_unit_op())
{
if (!join->having)
{
Item *where= join->conds;
if (join_tab[0].type == JT_EQ_REF &&
- join_tab[0].ref.items[0]->name == in_left_expr_name)
+ join_tab[0].ref.items[0]->name.str == in_left_expr_name.str)
{
remove_subq_pushed_predicates(join, &where);
save_index_subquery_explain_info(join_tab, where);
@@ -5015,7 +4991,7 @@ int rewrite_to_index_subquery_engine(JOIN *join)
where)));
}
else if (join_tab[0].type == JT_REF &&
- join_tab[0].ref.items[0]->name == in_left_expr_name)
+ join_tab[0].ref.items[0]->name.str == in_left_expr_name.str)
{
remove_subq_pushed_predicates(join, &where);
save_index_subquery_explain_info(join_tab, where);
@@ -5031,8 +5007,8 @@ int rewrite_to_index_subquery_engine(JOIN *join)
0)));
}
} else if (join_tab[0].type == JT_REF_OR_NULL &&
- join_tab[0].ref.items[0]->name == in_left_expr_name &&
- join->having->name == in_having_cond)
+ join_tab[0].ref.items[0]->name.str == in_left_expr_name.str &&
+ join->having->name.str == in_having_cond.str)
{
join_tab[0].type= JT_INDEX_SUBQUERY;
join->error= 0;
@@ -5063,7 +5039,7 @@ int rewrite_to_index_subquery_engine(JOIN *join)
static Item *remove_additional_cond(Item* conds)
{
- if (conds->name == in_additional_cond)
+ if (conds->name.str == in_additional_cond.str)
return 0;
if (conds->type() == Item::COND_ITEM)
{
@@ -5072,7 +5048,7 @@ static Item *remove_additional_cond(Item* conds)
Item *item;
while ((item= li++))
{
- if (item->name == in_additional_cond)
+ if (item->name.str == in_additional_cond.str)
{
li.remove();
if (cnd->argument_list()->elements == 1)
@@ -5335,7 +5311,7 @@ int select_value_catcher::setup(List<Item> *items)
List_iterator<Item> li(*items);
for (uint i= 0; (sel_item= li++); i++)
{
- if (!(row[i]= Item_cache::get_cache(thd, sel_item)))
+ if (!(row[i]= sel_item->get_cache(thd)))
return TRUE;
row[i]->setup(thd, sel_item);
}
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index b7010d1f8ed..d3d1bc97a70 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -1843,7 +1843,7 @@ void Dep_analysis_context::dbug_print_deps()
(long)(eq_mod - equality_mods),
str.c_ptr(),
eq_mod->field->table->table->alias.c_ptr(),
- eq_mod->field->field->field_name);
+ eq_mod->field->field->field_name.str);
}
else
{
@@ -1867,7 +1867,7 @@ void Dep_analysis_context::dbug_print_deps()
{
fprintf(DBUG_FILE, " field %s.%s ->",
table_dep->table->alias.c_ptr(),
- field_dep->field->field_name);
+ field_dep->field->field_name.str);
uint ofs= field_dep->bitmap_offset;
for (uint bit= ofs; bit < ofs + n_equality_mods; bit++)
{
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index 1cd294c1c7a..b091259d273 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -136,7 +136,7 @@ static ulonglong view_algo_from_frm(ulonglong val)
static my_bool
-write_parameter(IO_CACHE *file, uchar* base, File_option *parameter)
+write_parameter(IO_CACHE *file, const uchar* base, File_option *parameter)
{
char num_buf[20]; // buffer for numeric operations
// string for numeric operations
@@ -248,8 +248,9 @@ write_parameter(IO_CACHE *file, uchar* base, File_option *parameter)
my_bool
-sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
- const LEX_STRING *type,
+sql_create_definition_file(const LEX_CSTRING *dir,
+ const LEX_CSTRING *file_name,
+ const LEX_CSTRING *type,
uchar* base, File_option *parameters)
{
File handler;
@@ -399,7 +400,7 @@ my_bool rename_in_schema_file(THD *thd,
*/
File_parser *
-sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
+sql_parse_prepare(const LEX_CSTRING *file_name, MEM_ROOT *mem_root,
bool bad_format_errors)
{
MY_STAT stat_info;
@@ -598,13 +599,13 @@ read_escaped_string(const char *ptr, const char *eol, LEX_STRING *str)
const char *
parse_escaped_string(const char *ptr, const char *end, MEM_ROOT *mem_root,
- LEX_STRING *str)
+ LEX_CSTRING *str)
{
const char *eol= strchr(ptr, '\n');
if (eol == 0 || eol >= end ||
!(str->str= (char*) alloc_root(mem_root, (eol - ptr) + 1)) ||
- read_escaped_string(ptr, eol, str))
+ read_escaped_string(ptr, eol, (LEX_STRING*) str))
return 0;
return eol+1;
@@ -802,7 +803,7 @@ File_parser::parse(uchar* base, MEM_ROOT *mem_root,
case FILE_OPTIONS_ESTRING:
{
if (!(ptr= parse_escaped_string(ptr, end, mem_root,
- (LEX_STRING *)
+ (LEX_CSTRING *)
(base + parameter->offset))))
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
diff --git a/sql/parse_file.h b/sql/parse_file.h
index 87917dbd71b..3f48b2072db 100644
--- a/sql/parse_file.h
+++ b/sql/parse_file.h
@@ -42,7 +42,7 @@ enum file_opt_type {
struct File_option
{
- LEX_STRING name; /**< Name of the option */
+ LEX_CSTRING name; /**< Name of the option */
my_ptrdiff_t offset; /**< offset to base address of value */
file_opt_type type; /**< Option type */
};
@@ -82,15 +82,16 @@ bool get_file_options_ulllist(const char *&ptr, const char *end,
const char *
parse_escaped_string(const char *ptr, const char *end, MEM_ROOT *mem_root,
- LEX_STRING *str);
+ LEX_CSTRING *str);
class File_parser;
-File_parser *sql_parse_prepare(const LEX_STRING *file_name,
+File_parser *sql_parse_prepare(const LEX_CSTRING *file_name,
MEM_ROOT *mem_root, bool bad_format_errors);
my_bool
-sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
- const LEX_STRING *type,
+sql_create_definition_file(const LEX_CSTRING *dir,
+ const LEX_CSTRING *file_name,
+ const LEX_CSTRING *type,
uchar* base, File_option *parameters);
my_bool rename_in_schema_file(THD *thd,
const char *schema, const char *old_name,
@@ -99,19 +100,19 @@ my_bool rename_in_schema_file(THD *thd,
class File_parser: public Sql_alloc
{
char *start, *end;
- LEX_STRING file_type;
+ LEX_CSTRING file_type;
bool content_ok;
public:
File_parser() :start(0), end(0), content_ok(0)
{ file_type.str= 0; file_type.length= 0; }
bool ok() { return content_ok; }
- const LEX_STRING *type() const { return &file_type; }
+ const LEX_CSTRING *type() const { return &file_type; }
my_bool parse(uchar* base, MEM_ROOT *mem_root,
struct File_option *parameters, uint required,
Unknown_key_hook *hook) const;
- friend File_parser *sql_parse_prepare(const LEX_STRING *file_name,
+ friend File_parser *sql_parse_prepare(const LEX_CSTRING *file_name,
MEM_ROOT *mem_root,
bool bad_format_errors);
};
diff --git a/sql/partition_element.h b/sql/partition_element.h
index b979b7a58e6..c774994b7f5 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -96,14 +96,14 @@ public:
ha_rows part_max_rows;
ha_rows part_min_rows;
longlong range_value;
- char *partition_name;
- char *tablespace_name;
+ const char *partition_name;
+ const char *tablespace_name;
struct st_ddl_log_memory_entry *log_entry;
- char* part_comment;
- char* data_file_name;
- char* index_file_name;
+ const char* part_comment;
+ const char* data_file_name;
+ const char* index_file_name;
handlerton *engine_type;
- LEX_STRING connect_string;
+ LEX_CSTRING connect_string;
enum partition_state part_state;
uint16 nodegroup_id;
bool has_null_value;
@@ -115,7 +115,7 @@ public:
partition_name(NULL), tablespace_name(NULL),
log_entry(NULL), part_comment(NULL),
data_file_name(NULL), index_file_name(NULL),
- engine_type(NULL), connect_string(null_lex_str), part_state(PART_NORMAL),
+ engine_type(NULL), connect_string(null_clex_str), part_state(PART_NORMAL),
nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE),
signed_flag(FALSE), max_value(FALSE)
{
@@ -129,7 +129,7 @@ public:
data_file_name(part_elem->data_file_name),
index_file_name(part_elem->index_file_name),
engine_type(part_elem->engine_type),
- connect_string(null_lex_str),
+ connect_string(null_clex_str),
part_state(part_elem->part_state),
nodegroup_id(part_elem->nodegroup_id),
has_null_value(FALSE)
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 535ed4612e0..31e48a85104 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -562,10 +562,11 @@ bool partition_info::set_up_defaults_for_partitioning(THD *thd, handler *file,
Check that the user haven't defined the same field twice in
key or column list partitioning.
*/
-char* partition_info::find_duplicate_field()
+
+const char* partition_info::find_duplicate_field()
{
- char *field_name_outer, *field_name_inner;
- List_iterator<char> it_outer(part_field_list);
+ const char *field_name_outer, *field_name_inner;
+ List_iterator<const char> it_outer(part_field_list);
uint num_fields= part_field_list.elements;
uint i,j;
DBUG_ENTER("partition_info::find_duplicate_field");
@@ -573,7 +574,7 @@ char* partition_info::find_duplicate_field()
for (i= 0; i < num_fields; i++)
{
field_name_outer= it_outer++;
- List_iterator<char> it_inner(part_field_list);
+ List_iterator<const char> it_inner(part_field_list);
for (j= 0; j < num_fields; j++)
{
field_name_inner= it_inner++;
@@ -1384,7 +1385,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
handlerton *table_engine= default_engine_type;
uint i, tot_partitions;
bool result= TRUE, table_engine_set;
- char *same_name;
+ const char *same_name;
DBUG_ENTER("partition_info::check_partition_info");
DBUG_ASSERT(default_engine_type != partition_hton);
@@ -1919,7 +1920,7 @@ void partition_info::report_part_expr_error(bool use_subpart_expr)
!(type == HASH_PARTITION && list_of_fields))
{
my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
- item_field->name);
+ item_field->name.str);
DBUG_VOID_RETURN;
}
}
@@ -2647,9 +2648,9 @@ bool partition_info::has_same_partitioning(partition_info *new_part_info)
}
/* Check that it will use the same fields in KEY (fields) list. */
- List_iterator<char> old_field_name_it(part_field_list);
- List_iterator<char> new_field_name_it(new_part_info->part_field_list);
- char *old_name, *new_name;
+ List_iterator<const char> old_field_name_it(part_field_list);
+ List_iterator<const char> new_field_name_it(new_part_info->part_field_list);
+ const char *old_name, *new_name;
while ((old_name= old_field_name_it++))
{
new_name= new_field_name_it++;
@@ -2662,9 +2663,9 @@ bool partition_info::has_same_partitioning(partition_info *new_part_info)
if (is_sub_partitioned())
{
/* Check that it will use the same fields in KEY subpart fields list. */
- List_iterator<char> old_field_name_it(subpart_field_list);
- List_iterator<char> new_field_name_it(new_part_info->subpart_field_list);
- char *old_name, *new_name;
+ List_iterator<const char> old_field_name_it(subpart_field_list);
+ List_iterator<const char> new_field_name_it(new_part_info->subpart_field_list);
+ const char *old_name, *new_name;
while ((old_name= old_field_name_it++))
{
new_name= new_field_name_it++;
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 91ceee70ea4..38a353c8507 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -43,8 +43,8 @@ public:
List<partition_element> partitions;
List<partition_element> temp_partitions;
- List<char> part_field_list;
- List<char> subpart_field_list;
+ List<const char> part_field_list;
+ List<const char> subpart_field_list;
/*
If there is no subpartitioning, use only this func to get partition ids.
@@ -299,7 +299,7 @@ public:
bool set_up_defaults_for_partitioning(THD *thd, handler *file,
HA_CREATE_INFO *info,
uint start_no);
- char *find_duplicate_field();
+ const char *find_duplicate_field();
char *find_duplicate_name();
bool check_engine_mix(handlerton *engine_type, bool default_engine);
bool check_range_constants(THD *thd);
diff --git a/sql/procedure.cc b/sql/procedure.cc
index 8f9d6c0a7f3..3d36b7adfa3 100644
--- a/sql/procedure.cc
+++ b/sql/procedure.cc
@@ -89,7 +89,7 @@ setup_procedure(THD *thd,ORDER *param,select_result *result,
for (i=0 ; i < array_elements(sql_procs) ; i++)
{
if (!my_strcasecmp(system_charset_info,
- (*param->item)->name,sql_procs[i].name))
+ (*param->item)->name.str, sql_procs[i].name))
{
Procedure *proc=(*sql_procs[i].init)(thd,param,result,field_list);
*error= !proc;
diff --git a/sql/procedure.h b/sql/procedure.h
index b9d5066bb3d..a1c9b95f20b 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -40,13 +40,14 @@ class Item_proc :public Item
public:
Item_proc(THD *thd, const char *name_par): Item(thd)
{
- this->name=(char*) name_par;
+ this->name.str= name_par;
+ this->name.length= strlen(name_par);
}
enum Type type() const { return Item::PROC_ITEM; }
virtual void set(double nr)=0;
virtual void set(const char *str,uint length,CHARSET_INFO *cs)=0;
virtual void set(longlong nr)=0;
- virtual enum_field_types field_type() const=0;
+ const Type_handler *type_handler() const=0;
void set(const char *str) { set(str,(uint) strlen(str), default_charset()); }
void make_field(THD *thd, Send_field *tmp_field)
{
@@ -70,9 +71,7 @@ public:
{
decimals=dec; max_length=float_length(dec);
}
- 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; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
void set(double nr) { value=nr; }
void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs)
@@ -98,9 +97,7 @@ class Item_proc_int :public Item_proc
public:
Item_proc_int(THD *thd, const char *name_par): Item_proc(thd, name_par)
{ max_length=11; }
- enum Item_result result_type () const { return INT_RESULT; }
- enum Item_result cmp_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
void set(double nr) { value=(longlong) nr; }
void set(longlong nr) { value=nr; }
void set(const char *str,uint length, CHARSET_INFO *cs)
@@ -118,9 +115,7 @@ class Item_proc_string :public Item_proc
public:
Item_proc_string(THD *thd, const char *name_par, uint length):
Item_proc(thd, name_par) { this->max_length=length; }
- enum Item_result result_type () const { return STRING_RESULT; }
- enum Item_result cmp_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
void set(double nr) { str_value.set_real(nr, 2, default_charset()); }
void set(longlong nr) { str_value.set(nr, default_charset()); }
void set(const char *str, uint length, CHARSET_INFO *cs)
diff --git a/sql/protocol.cc b/sql/protocol.cc
index b9d9f28831e..33742dc01a2 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -791,8 +791,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
- uchar buff[MAX_FIELD_WIDTH];
- String tmp((char*) buff,sizeof(buff),&my_charset_bin);
+ ValueBuffer<MAX_FIELD_WIDTH> tmp;
Protocol_text prot(thd);
String *local_packet= prot.storage_packet();
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
@@ -800,7 +799,9 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
+ uchar buff[MAX_INT_WIDTH];
uchar *pos= net_store_length(buff, list->elements);
+ DBUG_ASSERT(pos <= buff + sizeof(buff));
if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
DBUG_RETURN(1);
}
@@ -840,9 +841,9 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
cs, thd_charset) ||
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
cs, thd_charset) ||
- prot.store(field.col_name, (uint) strlen(field.col_name),
+ prot.store(field.col_name.str, (uint) field.col_name.length,
cs, thd_charset) ||
- prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
+ prot.store(field.org_col_name.str, (uint) field.org_col_name.length,
cs, thd_charset) ||
local_packet->realloc(local_packet->length()+12))
goto err;
@@ -898,7 +899,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
if (prot.store(field.table_name, (uint) strlen(field.table_name),
cs, thd_charset) ||
- prot.store(field.col_name, (uint) strlen(field.col_name),
+ prot.store(field.col_name.str, (uint) field.col_name.length,
cs, thd_charset) ||
local_packet->realloc(local_packet->length()+10))
goto err;
@@ -968,15 +969,20 @@ bool Protocol::write()
bool Protocol::send_result_set_row(List<Item> *row_items)
{
- char buffer[MAX_FIELD_WIDTH];
- String str_buffer(buffer, sizeof (buffer), &my_charset_bin);
List_iterator_fast<Item> it(*row_items);
DBUG_ENTER("Protocol::send_result_set_row");
for (Item *item= it++; item; item= it++)
{
- if (item->send(this, &str_buffer))
+ /*
+ ValueBuffer::m_string can be altered during Item::send().
+ It's important to declare value_buffer inside the loop,
+ to have ValueBuffer::m_string point to ValueBuffer::buffer
+ on every iteration.
+ */
+ ValueBuffer<MAX_FIELD_WIDTH> value_buffer;
+ if (item->send(this, &value_buffer))
{
// If we're out of memory, reclaim some, to help us recover.
this->free();
@@ -985,12 +991,6 @@ bool Protocol::send_result_set_row(List<Item> *row_items)
/* Item::send() may generate an error. If so, abort the loop. */
if (thd->is_error())
DBUG_RETURN(TRUE);
-
- /*
- Reset str_buffer to its original state, as it may have been altered in
- Item::send().
- */
- str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
}
DBUG_RETURN(FALSE);
@@ -1116,7 +1116,7 @@ bool Protocol_text::store(const char *from, size_t length,
#ifndef DBUG_OFF
DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*s", field_pos,
field_count, (int) length, (length == 0 ? "" : from)));
- DBUG_ASSERT(field_pos < field_count);
+ DBUG_ASSERT(field_types == 0 || field_pos < field_count);
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 30b8b62b607..c385434e41e 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -981,24 +981,24 @@ rpl_slave_state::domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid)
Returns 0 on ok, non-zero on parse error.
*/
static int
-gtid_parser_helper(char **ptr, char *end, rpl_gtid *out_gtid)
+gtid_parser_helper(const char **ptr, const char *end, rpl_gtid *out_gtid)
{
char *q;
- char *p= *ptr;
+ const char *p= *ptr;
uint64 v1, v2, v3;
int err= 0;
- q= end;
+ q= (char*) end;
v1= (uint64)my_strtoll10(p, &q, &err);
if (err != 0 || v1 > (uint32)0xffffffff || q == end || *q != '-')
return 1;
p= q+1;
- q= end;
+ q= (char*) end;
v2= (uint64)my_strtoll10(p, &q, &err);
if (err != 0 || v2 > (uint32)0xffffffff || q == end || *q != '-')
return 1;
p= q+1;
- q= end;
+ q= (char*) end;
v3= (uint64)my_strtoll10(p, &q, &err);
if (err != 0)
return 1;
@@ -1014,8 +1014,8 @@ gtid_parser_helper(char **ptr, char *end, rpl_gtid *out_gtid)
rpl_gtid *
gtid_parse_string_to_list(const char *str, size_t str_len, uint32 *out_len)
{
- char *p= const_cast<char *>(str);
- char *end= p + str_len;
+ const char *p= const_cast<char *>(str);
+ const char *end= p + str_len;
uint32 len= 0, alloc_len= 5;
rpl_gtid *list= NULL;
@@ -1060,10 +1060,10 @@ gtid_parse_string_to_list(const char *str, size_t str_len, uint32 *out_len)
Returns 0 if ok, non-zero if error.
*/
int
-rpl_slave_state::load(THD *thd, char *state_from_master, size_t len,
+rpl_slave_state::load(THD *thd, const char *state_from_master, size_t len,
bool reset, bool in_statement)
{
- char *end= state_from_master + len;
+ const char *end= state_from_master + len;
if (reset)
{
@@ -1500,7 +1500,7 @@ rpl_binlog_state::read_from_iocache(IO_CACHE *src)
{
/* 10-digit - 10-digit - 20-digit \n \0 */
char buf[10+1+10+1+20+1+1];
- char *p, *end;
+ const char *p, *end;
rpl_gtid gtid;
int res= 0;
@@ -1763,9 +1763,9 @@ slave_connection_state::~slave_connection_state()
*/
int
-slave_connection_state::load(char *slave_request, size_t len)
+slave_connection_state::load(const char *slave_request, size_t len)
{
- char *p, *end;
+ const char *p, *end;
uchar *rec;
rpl_gtid *gtid;
const entry *e;
@@ -1779,7 +1779,7 @@ slave_connection_state::load(char *slave_request, size_t len)
{
if (!(rec= (uchar *)my_malloc(sizeof(entry), MYF(MY_WME))))
{
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*gtid));
+ my_error(ER_OUTOFMEMORY, MYF(0), (int) sizeof(*gtid));
return 1;
}
gtid= &((entry *)rec)->gtid;
@@ -2399,7 +2399,7 @@ gtid_waiting::get_entry(uint32 domain_id)
if (!(e= (hash_element *)my_malloc(sizeof(*e), MYF(MY_WME))))
{
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*e));
+ my_error(ER_OUTOFMEMORY, MYF(0), (int) sizeof(*e));
return NULL;
}
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index f638a084e38..5dfac7a3c6f 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -181,7 +181,7 @@ struct rpl_slave_state
bool sort);
int tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra);
bool domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid);
- int load(THD *thd, char *state_from_master, size_t len, bool reset,
+ int load(THD *thd, const char *state_from_master, size_t len, bool reset,
bool in_statement);
bool is_empty();
@@ -270,8 +270,12 @@ struct slave_connection_state
rpl_gtid gtid;
uint32 flags;
};
- static const uint32 START_OWN_SLAVE_POS= 0x1;
- static const uint32 START_ON_EMPTY_DOMAIN= 0x2;
+ /* Bits for 'flags' */
+ enum start_flags
+ {
+ START_OWN_SLAVE_POS= 0x1,
+ START_ON_EMPTY_DOMAIN= 0x2
+ };
/* Mapping from domain_id to the entry with GTID requested for that domain. */
HASH hash;
@@ -283,7 +287,7 @@ struct slave_connection_state
~slave_connection_state();
void reset() { my_hash_reset(&hash); }
- int load(char *slave_request, size_t len);
+ int load(const char *slave_request, size_t len);
int load(const rpl_gtid *gtid_list, uint32 count);
int load(rpl_slave_state *state, rpl_gtid *extra_gtids, uint32 num_extra);
rpl_gtid *find(uint32 domain_id);
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 093bc5df666..e90557efd0d 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -28,7 +28,7 @@
static void init_master_log_pos(Master_info* mi);
-Master_info::Master_info(LEX_STRING *connection_name_arg,
+Master_info::Master_info(LEX_CSTRING *connection_name_arg,
bool is_slave_recovery)
:Slave_reporting_capability("I/O"),
ssl(0), ssl_verify_server_cert(1), fd(-1), io_thd(0),
@@ -44,6 +44,7 @@ Master_info::Master_info(LEX_STRING *connection_name_arg,
in_start_all_slaves(0), in_stop_all_slaves(0), in_flush_all_relay_logs(0),
users(0), killed(0)
{
+ char *tmp;
host[0] = 0; user[0] = 0; password[0] = 0;
ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
ssl_cipher[0]= 0; ssl_key[0]= 0;
@@ -55,16 +56,14 @@ Master_info::Master_info(LEX_STRING *connection_name_arg,
*/
connection_name.length= cmp_connection_name.length=
connection_name_arg->length;
- if ((connection_name.str= (char*) my_malloc(connection_name_arg->length*2+2,
- MYF(MY_WME))))
+ if ((connection_name.str= tmp= (char*)
+ my_malloc(connection_name_arg->length*2+2, MYF(MY_WME))))
{
- cmp_connection_name.str= (connection_name.str +
- connection_name_arg->length+1);
- strmake(connection_name.str, connection_name_arg->str,
- connection_name.length);
- memcpy(cmp_connection_name.str, connection_name_arg->str,
- connection_name.length+1);
- my_casedn_str(system_charset_info, cmp_connection_name.str);
+ strmake(tmp, connection_name_arg->str, connection_name.length);
+ tmp+= connection_name_arg->length+1;
+ cmp_connection_name.str= tmp;
+ memcpy(tmp, connection_name_arg->str, connection_name.length+1);
+ my_casedn_str(system_charset_info, tmp);
}
/*
When MySQL restarted, all Rpl_filter settings which aren't in the my.cnf
@@ -124,7 +123,7 @@ Master_info::~Master_info()
#endif
rpl_filters.delete_element(connection_name.str, connection_name.length,
(void (*)(const char*, uchar*)) free_rpl_filter);
- my_free(connection_name.str);
+ my_free(const_cast<char*>(connection_name.str));
delete_dynamic(&ignore_server_ids);
mysql_mutex_destroy(&run_lock);
mysql_mutex_destroy(&data_lock);
@@ -901,7 +900,7 @@ void free_key_master_info(Master_info *mi)
1 error
*/
-bool check_master_connection_name(LEX_STRING *name)
+bool check_master_connection_name(LEX_CSTRING *name)
{
if (name->length >= MAX_CONNECTION_NAME)
return 1;
@@ -931,7 +930,7 @@ bool check_master_connection_name(LEX_STRING *name)
void create_logfile_name_with_suffix(char *res_file_name, size_t length,
const char *info_file, bool append,
- LEX_STRING *suffix)
+ LEX_CSTRING *suffix)
{
char buff[MAX_CONNECTION_NAME+1],
res[MAX_CONNECTION_NAME * MAX_FILENAME_MBWIDTH+1], *p;
@@ -1124,7 +1123,7 @@ bool Master_info_index::init_all_master_info()
while (!init_strvar_from_file(sign, sizeof(sign),
&index_file, NULL))
{
- LEX_STRING connection_name;
+ LEX_CSTRING connection_name;
Master_info *mi;
char buf_master_info_file[FN_REFLEN];
char buf_relay_log_info_file[FN_REFLEN];
@@ -1253,7 +1252,7 @@ error:
/* Write new master.info to master.info.index File */
-bool Master_info_index::write_master_name_to_index_file(LEX_STRING *name,
+bool Master_info_index::write_master_name_to_index_file(LEX_CSTRING *name,
bool do_sync)
{
DBUG_ASSERT(my_b_inited(&index_file) != 0);
@@ -1290,7 +1289,7 @@ bool Master_info_index::write_master_name_to_index_file(LEX_STRING *name,
WARN_LEVEL_ERROR-> Issue error if not exists
*/
-Master_info *get_master_info(const LEX_STRING *connection_name,
+Master_info *get_master_info(const LEX_CSTRING *connection_name,
Sql_condition::enum_warning_level warning)
{
Master_info *mi;
@@ -1356,7 +1355,7 @@ void Master_info::release()
*/
Master_info *
-Master_info_index::get_master_info(const LEX_STRING *connection_name,
+Master_info_index::get_master_info(const LEX_CSTRING *connection_name,
Sql_condition::enum_warning_level warning)
{
Master_info *mi;
@@ -1387,7 +1386,7 @@ Master_info_index::get_master_info(const LEX_STRING *connection_name,
/* Check Master_host & Master_port is duplicated or not */
-bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg,
+bool Master_info_index::check_duplicate_master_info(LEX_CSTRING *name_arg,
const char *host,
uint port)
{
@@ -1917,7 +1916,7 @@ char *Domain_id_filter::as_string(enum_list_type type)
{
ulong domain_id;
get_dynamic(ids, (void *) &domain_id, i);
- cur_len+= my_snprintf(buf + cur_len, sz, " %u", domain_id);
+ cur_len+= my_snprintf(buf + cur_len, sz, " %lu", domain_id);
sz-= cur_len;
}
return buf;
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
index d0f6171815c..ccc1be6e5ce 100644
--- a/sql/rpl_mi.h
+++ b/sql/rpl_mi.h
@@ -172,7 +172,7 @@ class Master_info : public Slave_reporting_capability
USE_GTID_NO= 0, USE_GTID_CURRENT_POS= 1, USE_GTID_SLAVE_POS= 2
};
- Master_info(LEX_STRING *connection_name, bool is_slave_recovery);
+ Master_info(LEX_CSTRING *connection_name, bool is_slave_recovery);
~Master_info();
bool shall_ignore_server_id(ulong s_id);
void clear_in_memory_info(bool all);
@@ -197,8 +197,8 @@ class Master_info : public Slave_reporting_capability
char host[HOSTNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
char user[USERNAME_LENGTH+1];
char password[MAX_PASSWORD_LENGTH*SYSTEM_CHARSET_MBMAXLEN+1];
- LEX_STRING connection_name; /* User supplied connection name */
- LEX_STRING cmp_connection_name; /* Connection name in lower case */
+ LEX_CSTRING connection_name; /* User supplied connection name */
+ LEX_CSTRING cmp_connection_name; /* Connection name in lower case */
bool ssl; // enables use of SSL connection if true
char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];
@@ -343,14 +343,14 @@ public:
HASH master_info_hash;
bool init_all_master_info();
- bool write_master_name_to_index_file(LEX_STRING *connection_name,
+ bool write_master_name_to_index_file(LEX_CSTRING *connection_name,
bool do_sync);
- bool check_duplicate_master_info(LEX_STRING *connection_name,
+ bool check_duplicate_master_info(LEX_CSTRING *connection_name,
const char *host, uint port);
bool add_master_info(Master_info *mi, bool write_to_file);
bool remove_master_info(Master_info *mi);
- Master_info *get_master_info(const LEX_STRING *connection_name,
+ Master_info *get_master_info(const LEX_CSTRING *connection_name,
Sql_condition::enum_warning_level warning);
bool start_all_slaves(THD *thd);
bool stop_all_slaves(THD *thd);
@@ -368,13 +368,13 @@ public:
};
-Master_info *get_master_info(const LEX_STRING *connection_name,
+Master_info *get_master_info(const LEX_CSTRING *connection_name,
Sql_condition::enum_warning_level warning);
-bool check_master_connection_name(LEX_STRING *name);
+bool check_master_connection_name(LEX_CSTRING *name);
void create_logfile_name_with_suffix(char *res_file_name, size_t length,
const char *info_file,
bool append,
- LEX_STRING *suffix);
+ LEX_CSTRING *suffix);
uchar *get_key_master_info(Master_info *mi, size_t *length,
my_bool not_used __attribute__((unused)));
diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h
index a0faeae815c..4579d0da9bc 100644
--- a/sql/rpl_parallel.h
+++ b/sql/rpl_parallel.h
@@ -68,23 +68,27 @@ struct group_commit_orderer {
*/
bool installed;
- /*
- This flag is set for a GCO in which we have event groups with multiple
- different commit_id values from the master. This happens when we
- optimistically try to execute in parallel transactions not known to be
- conflict-free.
-
- When this flag is set, in case of DDL we need to start a new GCO regardless
- of current commit_id, as DDL is not safe to speculatively apply in parallel
- with prior event groups.
- */
- static const uint8 MULTI_BATCH = 0x01;
- /*
- This flag is set for a GCO that contains DDL. If set, it forces a switch to
- a new GCO upon seeing a new commit_id, as DDL is not safe to speculatively
- replicate in parallel with subsequent transactions.
- */
- static const uint8 FORCE_SWITCH = 0x02;
+ enum force_switch_bits
+ {
+ /*
+ This flag is set for a GCO in which we have event groups with multiple
+ different commit_id values from the master. This happens when we
+ optimistically try to execute in parallel transactions not known to be
+ conflict-free.
+
+ When this flag is set, in case of DDL we need to start a new GCO
+ regardless of current commit_id, as DDL is not safe to
+ speculatively apply in parallel with prior event groups.
+ */
+ MULTI_BATCH= 1,
+ /*
+ This flag is set for a GCO that contains DDL. If set, it forces
+ a switch to a new GCO upon seeing a new commit_id, as DDL is not
+ safe to speculatively replicate in parallel with subsequent
+ transactions.
+ */
+ FORCE_SWITCH= 2
+ };
uint8 flags;
};
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index 0ef13c2cbb7..c07fe0464a1 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -107,7 +107,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
field->max_data_length());
DBUG_PRINT("debug", ("field: %s; real_type: %d, pack_ptr: 0x%lx;"
" pack_ptr':0x%lx; bytes: %d",
- field->field_name, field->real_type(),
+ field->field_name.str, field->real_type(),
(ulong) old_pack_ptr, (ulong) pack_ptr,
(int) (pack_ptr - old_pack_ptr)));
DBUG_DUMP("packed_data", old_pack_ptr, pack_ptr - old_pack_ptr);
@@ -254,7 +254,7 @@ unpack_row(rpl_group_info *rgi,
conv_field ? conv_field : *field_ptr;
DBUG_PRINT("debug", ("Conversion %srequired for field '%s' (#%ld)",
conv_field ? "" : "not ",
- (*field_ptr)->field_name,
+ (*field_ptr)->field_name.str,
(long) (field_ptr - begin_ptr)));
DBUG_ASSERT(f != NULL);
@@ -305,7 +305,7 @@ unpack_row(rpl_group_info *rgi,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BAD_NULL_ERROR,
ER_THD(thd, ER_BAD_NULL_ERROR),
- f->field_name);
+ f->field_name.str);
}
}
else
@@ -323,7 +323,7 @@ unpack_row(rpl_group_info *rgi,
pack_ptr= f->unpack(f->ptr, pack_ptr, row_end, metadata);
DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;"
" pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d",
- f->field_name, metadata,
+ f->field_name.str, metadata,
(ulong) old_pack_ptr, (ulong) pack_ptr,
(int) (pack_ptr - old_pack_ptr)));
if (!pack_ptr)
@@ -338,7 +338,7 @@ unpack_row(rpl_group_info *rgi,
WSREP_WARN("ROW event unpack field: %s metadata: 0x%x;"
" pack_ptr: 0x%lx; conv_table %p conv_field %p table %s"
" row_end: 0x%lx",
- f->field_name, metadata,
+ f->field_name.str, metadata,
(ulong) old_pack_ptr, conv_table, conv_field,
(table_found) ? "found" : "not found", (ulong)row_end
);
@@ -347,7 +347,7 @@ unpack_row(rpl_group_info *rgi,
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT,
rgi->gtid_info(),
"Could not read field '%s' of table '%s.%s'",
- f->field_name, table->s->db.str,
+ f->field_name.str, table->s->db.str,
table->s->table_name.str);
DBUG_RETURN(HA_ERR_CORRUPT_EVENT);
}
@@ -370,7 +370,7 @@ unpack_row(rpl_group_info *rgi,
conv_field->sql_type(source_type);
conv_field->val_str(&value_string);
DBUG_PRINT("debug", ("Copying field '%s' of type '%s' with value '%s'",
- (*field_ptr)->field_name,
+ (*field_ptr)->field_name.str,
source_type.c_ptr_safe(), value_string.c_ptr_safe()));
#endif
copy.set(*field_ptr, f, TRUE);
@@ -381,7 +381,7 @@ unpack_row(rpl_group_info *rgi,
(*field_ptr)->sql_type(target_type);
(*field_ptr)->val_str(&value_string);
DBUG_PRINT("debug", ("Value of field '%s' of type '%s' is now '%s'",
- (*field_ptr)->field_name,
+ (*field_ptr)->field_name.str,
target_type.c_ptr_safe(), value_string.c_ptr_safe()));
#endif
}
@@ -489,7 +489,7 @@ int prepare_record(TABLE *const table, const uint skip, const bool check)
Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_FIELD,
ER_THD(thd, ER_NO_DEFAULT_FOR_FIELD),
- f->field_name);
+ f->field_name.str);
}
}
diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc
index 5b876373b9c..a252bbff0f5 100644
--- a/sql/rpl_record_old.cc
+++ b/sql/rpl_record_old.cc
@@ -143,7 +143,7 @@ unpack_row_old(rpl_group_info *rgi,
{
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, NULL,
"Could not read field `%s` of table `%s`.`%s`",
- f->field_name, table->s->db.str,
+ f->field_name.str, table->s->db.str,
table->s->table_name.str);
return(ER_SLAVE_CORRUPT_EVENT);
}
@@ -186,7 +186,7 @@ unpack_row_old(rpl_group_info *rgi,
rgi->rli->report(ERROR_LEVEL, ER_NO_DEFAULT_FOR_FIELD, NULL,
"Field `%s` of table `%s`.`%s` "
"has no default value and cannot be NULL",
- (*field_ptr)->field_name, table->s->db.str,
+ (*field_ptr)->field_name.str, table->s->db.str,
table->s->table_name.str);
error = ER_NO_DEFAULT_FOR_FIELD;
}
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index bdf5b7dea80..9a984c5c953 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -825,7 +825,7 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi,
{
DBUG_PRINT("debug", ("Checking column %d -"
" field '%s' can be converted - order: %d",
- col, field->field_name, order));
+ col, field->field_name.str, order));
DBUG_ASSERT(order >= -1 && order <= 1);
/*
@@ -855,7 +855,7 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi,
{
DBUG_PRINT("debug", ("Checking column %d -"
" field '%s' can not be converted",
- col, field->field_name));
+ col, field->field_name.str));
DBUG_ASSERT(col < size() && col < table->s->fields);
DBUG_ASSERT(table->s->db.str && table->s->table_name.str);
DBUG_ASSERT(table->in_use);
@@ -891,7 +891,7 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi,
table->field[col]->sql_type(target_type);
DBUG_PRINT("debug", ("Field %s - conversion required."
" Source type: '%s', Target type: '%s'",
- tmp_table->field[col]->field_name,
+ tmp_table->field[col]->field_name.str,
source_type.c_ptr_safe(), target_type.c_ptr_safe()));
}
}
@@ -928,7 +928,7 @@ public:
(int) sql_type,
target_field->table->s->db.str,
target_field->table->s->table_name.str,
- target_field->field_name);
+ target_field->field_name.str);
return true;
}
Field *tmp= handler->make_conversion_table_field(this, metadata,
@@ -938,7 +938,7 @@ public:
Virtual_tmp_table::add(tmp);
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
- sql_type, target_field->field_name,
+ sql_type, target_field->field_name.str,
tmp->field_length, tmp->decimals(), TRUE,
tmp->flags, tmp->pack_length()));
return false;
@@ -980,7 +980,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
DBUG_PRINT("debug", ("binlog_type: %d, metadata: %04X, target_field: '%s'"
" make_conversion_table_field() failed",
binlog_type(col), field_metadata(col),
- target_table->field[col]->field_name));
+ target_table->field[col]->field_name.str));
goto err;
}
}
diff --git a/sql/session_tracker.cc b/sql/session_tracker.cc
index 03d4b150434..61680fb17f6 100644
--- a/sql/session_tracker.cc
+++ b/sql/session_tracker.cc
@@ -396,7 +396,7 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
return false;
}
- if(!strcmp(var_list.str,(const char *)"*"))
+ if(!strcmp(var_list.str, "*"))
{
track_all= true;
buffer_length= 2;
@@ -418,7 +418,7 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
for (;;)
{
sys_var *svar;
- LEX_STRING var;
+ LEX_CSTRING var;
uint not_used;
lasts= (char *) memchr(token, separator, rest);
@@ -435,7 +435,7 @@ bool Session_sysvars_tracker::vars_list::parse_var_list(THD *thd,
/* Remove leading/trailing whitespace. */
trim_whitespace(char_set, &var, &not_used);
- if(!strcmp(var.str,(const char *)"*"))
+ if(!strcmp(var.str, "*"))
{
track_all= true;
}
@@ -483,7 +483,7 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
size_t rest= var_list.length;
if (!var_list.str || var_list.length == 0 ||
- !strcmp(var_list.str,(const char *)"*"))
+ !strcmp(var_list.str, "*"))
{
return false;
}
@@ -500,7 +500,7 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
mysql_mutex_lock(&LOCK_plugin);
for (;;)
{
- LEX_STRING var;
+ LEX_CSTRING var;
uint not_used;
lasts= (char *) memchr(token, separator, rest);
@@ -517,7 +517,7 @@ bool Session_sysvars_tracker::check_var_list(THD *thd,
/* Remove leading/trailing whitespace. */
trim_whitespace(char_set, &var, &not_used);
- if(!strcmp(var.str,(const char *)"*") &&
+ if(!strcmp(var.str, "*") &&
!find_sys_var_ex(thd, var.str, var.length, throw_error, true))
{
if (throw_error && take_mutex && thd)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 07395e3e708..15f6bbdafc5 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -233,12 +233,12 @@ bool sys_var::update(THD *thd, set_var *var)
}
}
-uchar *sys_var::session_value_ptr(THD *thd, const LEX_STRING *base)
+uchar *sys_var::session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return session_var_ptr(thd);
}
-uchar *sys_var::global_value_ptr(THD *thd, const LEX_STRING *base)
+uchar *sys_var::global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return global_var_ptr();
}
@@ -271,7 +271,8 @@ bool sys_var::check(THD *thd, set_var *var)
return false;
}
-uchar *sys_var::value_ptr(THD *thd, enum_var_type type, const LEX_STRING *base)
+uchar *sys_var::value_ptr(THD *thd, enum_var_type type,
+ const LEX_CSTRING *base)
{
DBUG_ASSERT(base);
if (type == OPT_GLOBAL || scope() == GLOBAL)
@@ -327,7 +328,8 @@ do { \
break
longlong sys_var::val_int(bool *is_null,
- THD *thd, enum_var_type type, const LEX_STRING *base)
+ THD *thd, enum_var_type type,
+ const LEX_CSTRING *base)
{
LEX_STRING sval;
AutoWLock lock(&PLock_global_system_variables);
@@ -382,7 +384,7 @@ String *sys_var::val_str_nolock(String *str, THD *thd, const uchar *value)
String *sys_var::val_str(String *str,
- THD *thd, enum_var_type type, const LEX_STRING *base)
+ THD *thd, enum_var_type type, const LEX_CSTRING *base)
{
AutoWLock lock(&PLock_global_system_variables);
const uchar *value= value_ptr(thd, type, base);
@@ -391,7 +393,7 @@ String *sys_var::val_str(String *str,
double sys_var::val_real(bool *is_null,
- THD *thd, enum_var_type type, const LEX_STRING *base)
+ THD *thd, enum_var_type type, const LEX_CSTRING *base)
{
LEX_STRING sval;
AutoWLock lock(&PLock_global_system_variables);
@@ -686,6 +688,17 @@ sys_var *intern_find_sys_var(const char *str, uint length)
}
+bool find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
+{
+ tmp->var= find_sys_var(thd, tmp->base_name.str, tmp->base_name.length);
+
+ if (tmp->var != NULL)
+ tmp->base_name= null_clex_str;
+
+ return thd->is_error();
+}
+
+
/**
Execute update of all variables.
@@ -827,7 +840,7 @@ int set_var::update(THD *thd)
set_var::set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg,
- const LEX_STRING *base_name_arg, Item *value_arg)
+ const LEX_CSTRING *base_name_arg, Item *value_arg)
:var(var_arg), type(type_arg), base(*base_name_arg)
{
/*
@@ -838,7 +851,9 @@ set_var::set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg,
{
Item_field *item= (Item_field*) value_arg;
// names are utf8
- if (!(value= new (thd->mem_root) Item_string_sys(thd, item->field_name)))
+ if (!(value= new (thd->mem_root) Item_string_sys(thd,
+ item->field_name.str,
+ item->field_name.length)))
value=value_arg; /* Give error message later */
}
else
@@ -1050,7 +1065,7 @@ static void store_var(Field *field, sys_var *var, enum_var_type scope,
return;
store_value_ptr(field, var, str,
- var->value_ptr(field->table->in_use, scope, &null_lex_str));
+ var->value_ptr(field->table->in_use, scope, &null_clex_str));
}
int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
diff --git a/sql/set_var.h b/sql/set_var.h
index 97dc3b5ba51..17d1ff93ebc 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -112,7 +112,7 @@ public:
virtual sys_var_pluginvar *cast_pluginvar() { return 0; }
bool check(THD *thd, set_var *var);
- uchar *value_ptr(THD *thd, enum_var_type type, const LEX_STRING *base);
+ uchar *value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base);
/**
Update the system variable with the default value from either
@@ -123,9 +123,9 @@ public:
bool update(THD *thd, set_var *var);
String *val_str_nolock(String *str, THD *thd, const uchar *value);
- longlong val_int(bool *is_null, THD *thd, enum_var_type type, const LEX_STRING *base);
- String *val_str(String *str, THD *thd, enum_var_type type, const LEX_STRING *base);
- double val_real(bool *is_null, THD *thd, enum_var_type type, const LEX_STRING *base);
+ longlong val_int(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base);
+ String *val_str(String *str, THD *thd, enum_var_type type, const LEX_CSTRING *base);
+ double val_real(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base);
SHOW_TYPE show_type() { return show_val_type; }
int scope() const { return flags & SCOPE_MASK; }
@@ -229,8 +229,8 @@ protected:
It must be of show_val_type type (my_bool for SHOW_MY_BOOL,
int for SHOW_INT, longlong for SHOW_LONGLONG, etc).
*/
- virtual uchar *session_value_ptr(THD *thd, const LEX_STRING *base);
- virtual uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ virtual uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base);
+ virtual uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
/**
A pointer to a storage area of the variable, to the raw data.
@@ -290,10 +290,10 @@ public:
LEX_STRING string_value; ///< for Sys_var_charptr and others
const void *ptr; ///< for Sys_var_struct
} save_result;
- LEX_STRING base; /**< for structured variables, like keycache_name.variable_name */
+ LEX_CSTRING base; /**< for structured variables, like keycache_name.variable_name */
set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg,
- const LEX_STRING *base_name_arg, Item *value_arg);
+ const LEX_CSTRING *base_name_arg, Item *value_arg);
virtual bool is_system() { return 1; }
int check(THD *thd);
int update(THD *thd);
@@ -330,10 +330,10 @@ public:
class set_var_role: public set_var_base
{
- LEX_STRING role;
+ LEX_CSTRING role;
ulonglong access;
public:
- set_var_role(LEX_STRING role_arg) : role(role_arg) {}
+ set_var_role(LEX_CSTRING role_arg) : role(role_arg) {}
int check(THD *thd);
int update(THD *thd);
};
@@ -343,9 +343,9 @@ public:
class set_var_default_role: public set_var_base
{
LEX_USER *user, *real_user;
- LEX_STRING role;
+ LEX_CSTRING role;
public:
- set_var_default_role(LEX_USER *user_arg, LEX_STRING role_arg) :
+ set_var_default_role(LEX_USER *user_arg, LEX_CSTRING role_arg) :
user(user_arg), role(role_arg) {}
int check(THD *thd);
int update(THD *thd);
@@ -391,6 +391,7 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type);
int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond);
sys_var *find_sys_var(THD *thd, const char *str, size_t length=0);
+bool find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp);
int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free);
#define SYSVAR_AUTOSIZE(VAR,VAL) \
@@ -411,7 +412,8 @@ inline bool IS_SYSVAR_AUTOSIZE(void *ptr)
bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type);
sql_mode_t expand_sql_mode(sql_mode_t sql_mode);
-bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode, LEX_STRING *ls);
+bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
+ LEX_CSTRING *ls);
int default_regex_flags_pcre(const THD *thd);
extern sys_var *Sys_autocommit_ptr;
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 1f4cf315f1c..cfc544cc1bd 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -5202,7 +5202,7 @@ ER_FRM_UNKNOWN_TYPE
rus "Файл '%-.192s' Ñодержит неизвеÑтный тип '%-.64s' в заголовке"
ukr "Файл '%-.192s' має невідомий тип '%-.64s' у заголовку"
ER_WRONG_OBJECT
- eng "'%-.192s.%-.192s' is not %s"
+ eng "'%-.192s.%-.192s' is not of type '%s'"
ger "'%-.192s.%-.192s' ist nicht %s"
rus "'%-.192s.%-.192s' - не %s"
ukr "'%-.192s.%-.192s' не є %s"
@@ -5257,8 +5257,8 @@ ER_SP_GOTO_IN_HNDLR
eng "GOTO is not allowed in a stored procedure handler"
ger "GOTO ist im Handler einer gespeicherten Prozedur nicht erlaubt"
ER_TRG_ALREADY_EXISTS
- eng "Trigger already exists"
- ger "Trigger existiert bereits"
+ eng "Trigger '%s' already exists"
+ ger "Trigger '%s' existiert bereits"
ER_TRG_DOES_NOT_EXIST
eng "Trigger does not exist"
ger "Trigger existiert nicht"
@@ -6471,7 +6471,7 @@ ER_CANNOT_LOAD_FROM_TABLE_V2
ger "Kann %s.%s nicht einlesen. Tabelle ist wahrscheinlich beschädigt"
ER_MASTER_DELAY_VALUE_OUT_OF_RANGE
- eng "The requested value %u for the master delay exceeds the maximum %u"
+ eng "The requested value %lu for the master delay exceeds the maximum %lu"
ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT
eng "Only Format_description_log_event and row events are allowed in BINLOG statements (but %s was provided)"
@@ -7351,7 +7351,7 @@ ER_WITH_COL_WRONG_LIST
ER_TOO_MANY_DEFINITIONS_IN_WITH_CLAUSE
eng "Too many WITH elements in WITH clause"
ER_DUP_QUERY_NAME
- eng "Duplicate query name in WITH clause"
+ eng "Duplicate query name %`-.64s in WITH clause"
ER_RECURSIVE_WITHOUT_ANCHORS
eng "No anchors for recursive WITH element '%s'"
ER_UNACCEPTABLE_MUTUAL_RECURSION
@@ -7455,3 +7455,38 @@ ER_SLAVE_SAME_ID
eng "A slave with the same server_uuid/server_id as this slave has connected to the master"
ER_FLASHBACK_NOT_SUPPORTED
eng "Flashback does not support %s %s"
+ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
+ eng "Illegal parameter data types %s and %s for operation '%s'"
+ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
+ eng "Illegal parameter data type %s for operation '%s'"
+ER_WRONG_PARAMCOUNT_TO_CURSOR 42000
+ eng "Incorrect parameter count to cursor '%-.192s'"
+ rus "Ðекорректное количеÑтво параметров Ð´Ð»Ñ ÐºÑƒÑ€Ñора '%-.192s'"
+ER_UNKNOWN_STRUCTURED_VARIABLE
+ eng "Unknown structured system variable or ROW routine variable '%-.*s'"
+ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD
+ eng "Row variable '%-.192s' does not have a field '%-.192s'"
+ER_END_IDENTIFIER_DOES_NOT_MATCH
+ eng "END identifier '%-.192s' does not match '%-.192s'"
+ER_SEQUENCE_RUN_OUT
+ eng "Sequence '%-.64s.%-.64s' has run out"
+ER_SEQUENCE_INVALID_DATA
+ eng "Sequence '%-.64s.%-.64s' values are conflicting"
+ER_SEQUENCE_INVALID_TABLE_STRUCTURE
+ eng "Sequence '%-.64s.%-.64s' table structure is invalid (%s)"
+ER_SEQUENCE_ACCESS_ERROR
+ eng "Sequence '%-.64s.%-.64s' access error"
+ER_SEQUENCE_BINLOG_FORMAT
+ eng "Sequences requires binlog_format mixed or row"
+ER_NOT_SEQUENCE 42S02
+ eng "'%-.64s.%-.64s' is not a SEQUENCE"
+ER_NOT_SEQUENCE2 42S02
+ eng "'%-.192s' is not a SEQUENCE"
+ER_UNKNOWN_SEQUENCES 42S02
+ eng "Unknown SEQUENCE: '%-.300s'"
+ER_UNKNOWN_VIEW 42S02
+ eng "Unknown VIEW: '%-.300s'"
+ER_WRONG_INSERT_INTO_SEQUENCE
+ eng "Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a squence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead."
+ER_SP_STACK_TRACE
+ eng "At line %u in %s"
diff --git a/sql/slave.cc b/sql/slave.cc
index 3beb8df04eb..746d7c12ef1 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -82,7 +82,7 @@ ulonglong opt_read_binlog_speed_limit = 0;
const char *relay_log_index= 0;
const char *relay_log_basename= 0;
-LEX_STRING default_master_connection_name= { (char*) "", 0 };
+LEX_CSTRING default_master_connection_name= { (char*) "", 0 };
/*
When slave thread exits, we need to remember the temporary tables so we
@@ -3729,8 +3729,7 @@ int
apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd,
rpl_group_info *rgi)
{
- Relay_log_info* rli= rgi->rli;
- mysql_mutex_assert_not_owner(&rli->data_lock);
+ mysql_mutex_assert_not_owner(&rgi->rli->data_lock);
int reason= apply_event_and_update_pos_setup(ev, thd, rgi);
/*
In parallel replication, sql_slave_skip_counter is handled in the SQL
diff --git a/sql/slave.h b/sql/slave.h
index ded9d76e49d..431e6847abe 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -273,7 +273,7 @@ extern bool volatile abort_loop;
extern Master_info *active_mi; /* active_mi for multi-master */
extern Master_info *default_master_info; /* To replace active_mi */
extern Master_info_index *master_info_index;
-extern LEX_STRING default_master_connection_name;
+extern LEX_CSTRING default_master_connection_name;
extern my_bool replicate_same_server_id;
extern int disconnect_slave_event_count, abort_slave_event_count ;
diff --git a/sql/sp.cc b/sql/sp.cc
index 383eef9f5ce..c80078ebe19 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -35,15 +35,15 @@
#include <my_user.h>
/* Used in error handling only */
-#define SP_TYPE_STRING(type) \
- (type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
+#define SP_TYPE_STRING(type) stored_procedure_type_to_str(type)
static int
-db_load_routine(THD *thd, stored_procedure_type type, sp_name *name,
+db_load_routine(THD *thd, stored_procedure_type type, const sp_name *name,
sp_head **sphp,
sql_mode_t sql_mode, const char *params, const char *returns,
- const char *body, st_sp_chistics &chistics,
- LEX_STRING *definer_user_name, LEX_STRING *definer_host_name,
+ const char *body, const st_sp_chistics &chistics,
+ LEX_CSTRING *definer_user_name,
+ LEX_CSTRING *definer_host_name,
longlong created, longlong modified,
Stored_program_creation_ctx *creation_ctx);
@@ -470,7 +470,8 @@ static TABLE *open_proc_table_for_update(THD *thd)
*/
static int
-db_find_routine_aux(THD *thd, stored_procedure_type type, sp_name *name,
+db_find_routine_aux(THD *thd, stored_procedure_type type,
+ const Database_qualified_name *name,
TABLE *table)
{
uchar key[MAX_KEY_LENGTH]; // db, name, optional key length type
@@ -487,9 +488,8 @@ db_find_routine_aux(THD *thd, stored_procedure_type type, sp_name *name,
*/
if (name->m_name.length > table->field[1]->field_length)
DBUG_RETURN(SP_KEY_NOT_FOUND);
- table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin);
- table->field[1]->store(name->m_name.str, name->m_name.length,
- &my_charset_bin);
+ table->field[0]->store(name->m_db, &my_charset_bin);
+ table->field[1]->store(name->m_name, &my_charset_bin);
table->field[2]->store((longlong) type, TRUE);
key_copy(key, table->record[0], table->key_info,
table->key_info->key_length);
@@ -524,7 +524,7 @@ db_find_routine_aux(THD *thd, stored_procedure_type type, sp_name *name,
*/
static int
-db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
+db_find_routine(THD *thd, stored_procedure_type type, const sp_name *name,
sp_head **sphp)
{
TABLE *table;
@@ -533,7 +533,7 @@ db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
const char *definer;
longlong created;
longlong modified;
- st_sp_chistics chistics;
+ Sp_chistics chistics;
char *ptr;
uint length;
char buff[65];
@@ -543,9 +543,9 @@ db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
Open_tables_backup open_tables_state_backup;
Stored_program_creation_ctx *creation_ctx;
char definer_user_name_holder[USERNAME_LENGTH + 1];
- LEX_STRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH };
+ LEX_CSTRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH };
char definer_host_name_holder[HOSTNAME_LENGTH + 1];
- LEX_STRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH };
+ LEX_CSTRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH };
DBUG_ENTER("db_find_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",
@@ -567,7 +567,6 @@ db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
goto done;
}
- bzero((char *)&chistics, sizeof(chistics));
if ((ptr= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL)
{
@@ -655,9 +654,10 @@ db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
close_system_tables(thd, &open_tables_state_backup);
table= 0;
+ /* It's ok to cast to char* here as the pointers are to local buffers */
if (parse_user(definer, strlen(definer),
- definer_user_name.str, &definer_user_name.length,
- definer_host_name.str, &definer_host_name.length) &&
+ (char*) definer_user_name.str, &definer_user_name.length,
+ (char*) definer_host_name.str, &definer_host_name.length) &&
definer_user_name.length && !definer_host_name.length)
{
// 'user@' -> 'user@%'
@@ -810,10 +810,11 @@ Bad_db_error_handler::handle_condition(THD *thd,
static int
db_load_routine(THD *thd, stored_procedure_type type,
- sp_name *name, sp_head **sphp,
+ const sp_name *name, sp_head **sphp,
sql_mode_t sql_mode, const char *params, const char *returns,
- const char *body, st_sp_chistics &chistics,
- LEX_STRING *definer_user_name, LEX_STRING *definer_host_name,
+ const char *body, const st_sp_chistics &chistics,
+ LEX_CSTRING *definer_user_name,
+ LEX_CSTRING *definer_host_name,
longlong created, longlong modified,
Stored_program_creation_ctx *creation_ctx)
{
@@ -847,7 +848,7 @@ db_load_routine(THD *thd, stored_procedure_type type,
params, strlen(params),
returns, strlen(returns),
body, strlen(body),
- &chistics, definer_user_name, definer_host_name,
+ chistics, definer_user_name, definer_host_name,
sql_mode))
{
ret= SP_INTERNAL_ERROR;
@@ -885,7 +886,9 @@ db_load_routine(THD *thd, stored_procedure_type type,
generate an error.
*/
- if (cur_db_changed && mysql_change_db(thd, &saved_cur_db_name, TRUE))
+ if (cur_db_changed && mysql_change_db(thd,
+ (LEX_CSTRING*) &saved_cur_db_name,
+ TRUE))
{
ret= SP_INTERNAL_ERROR;
goto end;
@@ -898,7 +901,7 @@ db_load_routine(THD *thd, stored_procedure_type type,
}
(*sphp)->set_definer(definer_user_name, definer_host_name);
- (*sphp)->set_info(created, modified, &chistics, sql_mode);
+ (*sphp)->set_info(created, modified, chistics, sql_mode);
(*sphp)->set_creation_ctx(creation_ctx);
(*sphp)->optimize();
/*
@@ -967,7 +970,7 @@ sp_returns_type(THD *thd, String &result, sp_head *sp)
*/
static int
sp_drop_routine_internal(THD *thd, stored_procedure_type type,
- sp_name *name, TABLE *table)
+ const Database_qualified_name *name, TABLE *table)
{
DBUG_ENTER("sp_drop_routine_internal");
@@ -1024,7 +1027,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
bool ret= TRUE;
TABLE *table;
char definer_buf[USER_HOST_BUFF_SIZE];
- LEX_STRING definer;
+ LEX_CSTRING definer;
sql_mode_t saved_mode= thd->variables.sql_mode;
MDL_key::enum_mdl_namespace mdl_type= type == TYPE_ENUM_FUNCTION ?
MDL_key::FUNCTION : MDL_key::PROCEDURE;
@@ -1077,11 +1080,11 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
else
{
/* Checking if the routine already exists */
- if (db_find_routine_aux(thd, type, lex->spname, table) == SP_OK)
+ if (db_find_routine_aux(thd, type, sp, table) == SP_OK)
{
if (lex->create_info.or_replace())
{
- if ((ret= sp_drop_routine_internal(thd, type, lex->spname, table)))
+ if ((ret= sp_drop_routine_internal(thd, type, sp, table)))
goto done;
}
else if (lex->create_info.if_not_exists())
@@ -1090,7 +1093,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
ER_SP_ALREADY_EXISTS,
ER_THD(thd, ER_SP_ALREADY_EXISTS),
SP_TYPE_STRING(type),
- lex->spname->m_name.str);
+ sp->m_name.str);
ret= FALSE;
@@ -1135,11 +1138,11 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed=
table->field[MYSQL_PROC_FIELD_DB]->
- store(sp->m_db.str, sp->m_db.length, system_charset_info);
+ store(sp->m_db, system_charset_info);
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_NAME]->
- store(sp->m_name.str, sp->m_name.length, system_charset_info);
+ store(sp->m_name, system_charset_info);
store_failed= store_failed ||
table->field[MYSQL_PROC_MYSQL_TYPE]->
@@ -1147,29 +1150,29 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
- store(sp->m_name.str, sp->m_name.length, system_charset_info);
+ store(sp->m_name, system_charset_info);
- if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS)
+ if (sp->daccess() != SP_DEFAULT_ACCESS)
{
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_ACCESS]->
- store((longlong)sp->m_chistics->daccess, TRUE);
+ store((longlong)sp->daccess(), TRUE);
}
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
- store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE);
+ store((longlong)(sp->detistic() ? 1 : 2), TRUE);
- if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID)
+ if (sp->suid() != SP_IS_DEFAULT_SUID)
{
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
- store((longlong)sp->m_chistics->suid, TRUE);
+ store((longlong)sp->suid(), TRUE);
}
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
- store(sp->m_params.str, sp->m_params.length, system_charset_info);
+ store(sp->m_params, system_charset_info);
if (sp->m_type == TYPE_ENUM_FUNCTION)
{
@@ -1182,11 +1185,11 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_BODY]->
- store(sp->m_body.str, sp->m_body.length, system_charset_info);
+ store(sp->m_body, system_charset_info);
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_DEFINER]->
- store(definer.str, definer.length, system_charset_info);
+ store(definer, system_charset_info);
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
@@ -1195,26 +1198,25 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
table->field[MYSQL_PROC_FIELD_SQL_MODE]->
store((longlong)saved_mode, TRUE);
- if (sp->m_chistics->comment.str)
+ if (sp->comment().str)
{
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_COMMENT]->
- store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
- system_charset_info);
+ store(sp->comment(), system_charset_info);
}
if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
!trust_function_creators && mysql_bin_log.is_open())
{
- if (!sp->m_chistics->detistic)
+ if (!sp->detistic())
{
/*
Note that this test is not perfect; one could use
a non-deterministic read-only function in an update statement.
*/
enum enum_sp_data_access access=
- (sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
- SP_DEFAULT_ACCESS_MAPPING : sp->m_chistics->daccess;
+ (sp->daccess() == SP_DEFAULT_ACCESS) ?
+ SP_DEFAULT_ACCESS_MAPPING : sp->daccess();
if (access == SP_CONTAINS_SQL ||
access == SP_MODIFIES_SQL_DATA)
{
@@ -1251,7 +1253,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull();
store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store(
- sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info);
+ sp->m_body_utf8, system_charset_info);
if (store_failed)
{
@@ -1287,7 +1289,7 @@ log:
sp->m_params.str, sp->m_params.length,
retstr.ptr(), retstr.length(),
sp->m_body.str, sp->m_body.length,
- sp->m_chistics, &(thd->lex->definer->user),
+ sp->chistics(), &(thd->lex->definer->user),
&(thd->lex->definer->host),
saved_mode))
{
@@ -1333,7 +1335,7 @@ done:
*/
int
-sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name)
+sp_drop_routine(THD *thd, stored_procedure_type type, const sp_name *name)
{
TABLE *table;
int ret;
@@ -1387,8 +1389,8 @@ sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name)
*/
int
-sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
- st_sp_chistics *chistics)
+sp_update_routine(THD *thd, stored_procedure_type type, const sp_name *name,
+ const st_sp_chistics *chistics)
{
TABLE *table;
int ret;
@@ -1444,8 +1446,7 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
table->field[MYSQL_PROC_FIELD_ACCESS]->
store((longlong)chistics->daccess, TRUE);
if (chistics->comment.str)
- table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
- chistics->comment.length,
+ table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment,
system_charset_info);
if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) &&
ret != HA_ERR_RECORD_IS_THE_SAME)
@@ -1502,7 +1503,7 @@ public:
cases.
*/
-bool lock_db_routines(THD *thd, char *db)
+bool lock_db_routines(THD *thd, const char *db)
{
TABLE *table;
uint key_len;
@@ -1588,7 +1589,7 @@ bool lock_db_routines(THD *thd, char *db)
*/
int
-sp_drop_db_routines(THD *thd, char *db)
+sp_drop_db_routines(THD *thd, const char *db)
{
TABLE *table;
int ret;
@@ -1671,7 +1672,8 @@ err:
*/
bool
-sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name)
+sp_show_create_routine(THD *thd,
+ stored_procedure_type type, const sp_name *name)
{
sp_head *sp;
@@ -1699,8 +1701,7 @@ sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name)
If we have insufficient privileges, pretend the routine
does not exist.
*/
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE",
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), stored_procedure_type_to_str(type),
name->m_name.str);
DBUG_RETURN(TRUE);
}
@@ -1727,7 +1728,7 @@ sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name)
*/
sp_head *
-sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
+sp_find_routine(THD *thd, stored_procedure_type type, const sp_name *name,
sp_cache **cp, bool cache_only)
{
sp_head *sp;
@@ -1788,8 +1789,8 @@ sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
}
if (db_load_routine(thd, type, name, &new_sp,
sp->m_sql_mode, sp->m_params.str, returns,
- sp->m_body.str, *sp->m_chistics,
- &sp->m_definer_user, &sp->m_definer_host,
+ sp->m_body.str, sp->chistics(),
+ &sp->m_definer.user, &sp->m_definer.host,
sp->m_created, sp->m_modified,
sp->get_creation_ctx()) == SP_OK)
{
@@ -1841,14 +1842,12 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool is_proc)
for (routine= routines; routine; routine= routine->next_global)
{
sp_name *name;
- LEX_STRING lex_db;
- LEX_STRING lex_name;
- lex_db.length= strlen(routine->db);
- lex_name.length= strlen(routine->table_name);
- lex_db.str= thd->strmake(routine->db, lex_db.length);
- lex_name.str= thd->strmake(routine->table_name, lex_name.length);
- name= new sp_name(lex_db, lex_name, true);
- name->init_qname(thd);
+ LEX_CSTRING lex_db;
+ LEX_CSTRING lex_name;
+ thd->make_lex_string(&lex_db, routine->db, strlen(routine->db));
+ thd->make_lex_string(&lex_name, routine->table_name,
+ strlen(routine->table_name));
+ name= new sp_name(&lex_db, &lex_name, true);
sp_object_found= is_proc ? sp_find_routine(thd, TYPE_ENUM_PROCEDURE,
name, &thd->sp_proc_cache,
FALSE) != NULL :
@@ -1953,7 +1952,7 @@ bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
*/
void sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
- sp_name *rt, enum stored_procedure_type rt_type)
+ const sp_name *rt, enum stored_procedure_type rt_type)
{
MDL_key key((rt_type == TYPE_ENUM_FUNCTION) ? MDL_key::FUNCTION :
MDL_key::PROCEDURE,
@@ -2126,7 +2125,8 @@ int sp_cache_routine(THD *thd, Sroutine_hash_entry *rt,
@retval non-0 Error while loading routine from mysql,proc table.
*/
-int sp_cache_routine(THD *thd, enum stored_procedure_type type, sp_name *name,
+int sp_cache_routine(THD *thd, enum stored_procedure_type type,
+ const sp_name *name,
bool lookup_only, sp_head **sp)
{
int ret= 0;
@@ -2175,20 +2175,8 @@ int sp_cache_routine(THD *thd, enum stored_procedure_type type, sp_name *name,
*/
if (! thd->is_error())
{
- /*
- SP allows full NAME_LEN chars thus he have to allocate enough
- size in bytes. Otherwise there is stack overrun could happen
- if multibyte sequence is `name`. `db` is still safe because the
- rest of the server checks agains NAME_LEN bytes and not chars.
- Hence, the overrun happens only if the name is in length > 32 and
- uses multibyte (cyrillic, greek, etc.)
- */
- char n[NAME_LEN*2+2];
-
- /* m_qname.str is not always \0 terminated */
- memcpy(n, name->m_qname.str, name->m_qname.length);
- n[name->m_qname.length]= '\0';
- my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), n, ret);
+ my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0),
+ ErrConvDQName(name).ptr(), ret);
}
break;
}
@@ -2210,15 +2198,15 @@ show_create_sp(THD *thd, String *buf,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
- st_sp_chistics *chistics,
- const LEX_STRING *definer_user,
- const LEX_STRING *definer_host,
+ const st_sp_chistics &chistics,
+ const LEX_CSTRING *definer_user,
+ const LEX_CSTRING *definer_host,
sql_mode_t sql_mode)
{
sql_mode_t old_sql_mode= thd->variables.sql_mode;
/* Make some room to begin with */
if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen +
- chistics->comment.length + 10 /* length of " DEFINER= "*/ +
+ chistics.comment.length + 10 /* length of " DEFINER= "*/ +
USER_HOST_BUFF_SIZE))
return FALSE;
@@ -2245,11 +2233,14 @@ show_create_sp(THD *thd, String *buf,
buf->append(')');
if (type == TYPE_ENUM_FUNCTION)
{
- buf->append(STRING_WITH_LEN(" RETURNS "));
+ if (sql_mode & MODE_ORACLE)
+ buf->append(STRING_WITH_LEN(" RETURN "));
+ else
+ buf->append(STRING_WITH_LEN(" RETURNS "));
buf->append(returns, returnslen);
}
buf->append('\n');
- switch (chistics->daccess) {
+ switch (chistics.daccess) {
case SP_NO_SQL:
buf->append(STRING_WITH_LEN(" NO SQL\n"));
break;
@@ -2264,14 +2255,14 @@ show_create_sp(THD *thd, String *buf,
/* Do nothing */
break;
}
- if (chistics->detistic)
+ if (chistics.detistic)
buf->append(STRING_WITH_LEN(" DETERMINISTIC\n"));
- if (chistics->suid == SP_IS_NOT_SUID)
+ if (chistics.suid == SP_IS_NOT_SUID)
buf->append(STRING_WITH_LEN(" SQL SECURITY INVOKER\n"));
- if (chistics->comment.length)
+ if (chistics.comment.length)
{
buf->append(STRING_WITH_LEN(" COMMENT "));
- append_unescaped(buf, chistics->comment.str, chistics->comment.length);
+ append_unescaped(buf, chistics.comment.str, chistics.comment.length);
buf->append('\n');
}
buf->append(body, bodylen);
@@ -2309,11 +2300,10 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
{
const char *sp_body;
String defstr;
- struct st_sp_chistics sp_chistics;
- const LEX_STRING definer_user= {(char*)STRING_WITH_LEN("")};
- const LEX_STRING definer_host= {(char*)STRING_WITH_LEN("")};
- LEX_STRING sp_db_str;
- LEX_STRING sp_name_str;
+ const LEX_CSTRING definer_user= {STRING_WITH_LEN("")};
+ const LEX_CSTRING definer_host= {STRING_WITH_LEN("")};
+ LEX_CSTRING sp_db_str;
+ LEX_CSTRING sp_name_str;
sp_head *sp;
sp_cache **spc= ((type == TYPE_ENUM_PROCEDURE) ?
&thd->sp_proc_cache : &thd->sp_func_cache);
@@ -2321,8 +2311,7 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
sp_db_str.length= db->length();
sp_name_str.str= name->c_ptr();
sp_name_str.length= name->length();
- sp_name sp_name_obj(sp_db_str, sp_name_str, true);
- sp_name_obj.init_qname(thd);
+ sp_name sp_name_obj(&sp_db_str, &sp_name_str, true);
*free_sp_head= 0;
if ((sp= sp_cache_lookup(spc, &sp_name_obj)))
{
@@ -2333,7 +2322,6 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
Stored_program_creation_ctx *creation_ctx=
Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table);
sp_body= (type == TYPE_ENUM_FUNCTION ? "RETURN NULL" : "BEGIN END");
- bzero((char*) &sp_chistics, sizeof(sp_chistics));
defstr.set_charset(creation_ctx->get_client_cs());
if (!show_create_sp(thd, &defstr, type,
sp_db_str.str, sp_db_str.length,
@@ -2341,7 +2329,7 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
params, strlen(params),
returns, strlen(returns),
sp_body, strlen(sp_body),
- &sp_chistics, &definer_user, &definer_host, sql_mode))
+ Sp_chistics(), &definer_user, &definer_host, sql_mode))
return 0;
thd->lex= &newlex;
diff --git a/sql/sp.h b/sql/sp.h
index 96d49cfe676..dc93b8b20ee 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -48,6 +48,20 @@ enum stored_procedure_type
TYPE_ENUM_PROXY=4
};
+
+static inline const char *
+stored_procedure_type_to_str(enum stored_procedure_type type)
+{
+ switch (type) {
+ case TYPE_ENUM_PROCEDURE: return "PROCEDURE";
+ case TYPE_ENUM_FUNCTION: return "FUNCTION";
+ case TYPE_ENUM_TRIGGER: return "TRIGGER";
+ case TYPE_ENUM_PROXY: return "PROXY";
+ }
+ DBUG_ASSERT(0);
+ return "UNKNOWN_STORED_";
+}
+
/* Tells what SP_DEFAULT_ACCESS should be mapped to */
#define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL
@@ -93,7 +107,7 @@ enum
/* Drop all routines in database 'db' */
int
-sp_drop_db_routines(THD *thd, char *db);
+sp_drop_db_routines(THD *thd, const char *db);
/**
Acquires exclusive metadata lock on all stored routines in the
@@ -105,10 +119,10 @@ sp_drop_db_routines(THD *thd, char *db);
@retval false Success
@retval true Failure
*/
-bool lock_db_routines(THD *thd, char *db);
+bool lock_db_routines(THD *thd, const char *db);
sp_head *
-sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
+sp_find_routine(THD *thd, stored_procedure_type type, const sp_name *name,
sp_cache **cp, bool cache_only);
int
@@ -117,24 +131,24 @@ sp_cache_routine(THD *thd, Sroutine_hash_entry *rt,
int
-sp_cache_routine(THD *thd, stored_procedure_type type, sp_name *name,
+sp_cache_routine(THD *thd, stored_procedure_type type, const sp_name *name,
bool lookup_only, sp_head **sp);
bool
sp_exist_routines(THD *thd, TABLE_LIST *procs, bool is_proc);
bool
-sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name);
+sp_show_create_routine(THD *thd, stored_procedure_type type, const sp_name *name);
bool
sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp);
int
-sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
- st_sp_chistics *chistics);
+sp_update_routine(THD *thd, stored_procedure_type type, const sp_name *name,
+ const st_sp_chistics *chistics);
int
-sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name);
+sp_drop_routine(THD *thd, stored_procedure_type type, const sp_name *name);
/**
@@ -178,7 +192,7 @@ public:
Procedures for handling sets of stored routines used by statement or routine.
*/
void sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
- sp_name *rt, stored_procedure_type rt_type);
+ const sp_name *rt, stored_procedure_type rt_type);
bool sp_add_used_routine(Query_tables_list *prelocking_ctx, Query_arena *arena,
const MDL_key *key, TABLE_LIST *belong_to_view);
void sp_remove_not_own_routines(Query_tables_list *prelocking_ctx);
@@ -226,8 +240,8 @@ bool show_create_sp(THD *thd, String *buf,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
- st_sp_chistics *chistics,
- const LEX_STRING *definer_user,
- const LEX_STRING *definer_host,
+ const st_sp_chistics &chistics,
+ const LEX_CSTRING *definer_user,
+ const LEX_CSTRING *definer_host,
sql_mode_t sql_mode);
#endif /* _SP_H_ */
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index bafd0f34ab6..70ba5084914 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -167,8 +167,7 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp)
}
/* Reading a ulong variable with no lock. */
sp->set_sp_cache_version(Cversion);
- DBUG_PRINT("info",("sp_cache: inserting: %.*s", (int) sp->m_qname.length,
- sp->m_qname.str));
+ DBUG_PRINT("info",("sp_cache: inserting: %s", ErrConvDQName(sp).ptr()));
c->insert(sp);
*cp= c; // Update *cp if it was NULL
}
@@ -190,12 +189,13 @@ void sp_cache_insert(sp_cache **cp, sp_head *sp)
NULL if the routine not found.
*/
-sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name)
+sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name)
{
+ char buf[NAME_LEN * 2 + 2];
sp_cache *c= *cp;
if (! c)
return NULL;
- return c->lookup(name->m_qname.str, name->m_qname.length);
+ return c->lookup(buf, name->make_qname(buf, sizeof(buf)));
}
diff --git a/sql/sp_cache.h b/sql/sp_cache.h
index b21d4c4bf25..51886a61ee9 100644
--- a/sql/sp_cache.h
+++ b/sql/sp_cache.h
@@ -32,7 +32,7 @@
class sp_head;
class sp_cache;
-class sp_name;
+class Database_qualified_name;
/*
Cache usage scenarios:
@@ -59,7 +59,7 @@ void sp_cache_init();
void sp_cache_end();
void sp_cache_clear(sp_cache **cp);
void sp_cache_insert(sp_cache **cp, sp_head *sp);
-sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);
+sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name);
void sp_cache_invalidate();
void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp);
ulong sp_cache_version();
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index a31060179e4..bb3275316cc 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -23,8 +23,6 @@
#include "probes_mysql.h"
#include "sql_show.h" // append_identifier
#include "sql_db.h" // mysql_opt_change_db, mysql_change_db
-#include "sql_table.h" // sp_prepare_create_field,
- // prepare_create_field
#include "sql_acl.h" // *_ACL
#include "sql_array.h" // Dynamic_array
#include "log_event.h" // Query_log_event
@@ -94,67 +92,45 @@ sp_map_item_type(enum enum_field_types type)
}
-/**
- Return a string representation of the Item value.
-
- @param thd thread handle
- @param str string buffer for representation of the value
-
- @note
- If the item has a string result type, the string is escaped
- according to its character set.
+bool Item_splocal::append_for_log(THD *thd, String *str)
+{
+ if (fix_fields(thd, NULL))
+ return true;
- @retval
- NULL on error
- @retval
- non-NULL a pointer to valid a valid string on success
-*/
+ if (limit_clause_param)
+ return str->append_ulonglong(val_uint());
-static String *
-sp_get_item_value(THD *thd, Item *item, String *str)
-{
- switch (item->result_type()) {
- case REAL_RESULT:
- case INT_RESULT:
- case DECIMAL_RESULT:
- if (item->field_type() != MYSQL_TYPE_BIT)
- return item->val_str(str);
- else {/* Bit type is handled as binary string */}
- /* fall through */
- case STRING_RESULT:
- {
- String *result= item->val_str(str);
+ /*
+ ROW variables are currently not allowed in select_list, e.g.:
+ SELECT row_variable;
+ ROW variables can appear in query parts where name is not important, e.g.:
+ SELECT ROW(1,2)=row_variable FROM t1;
+ So we can skip using NAME_CONST() and use ROW() constants directly.
+ */
+ if (type_handler() == &type_handler_row)
+ return append_value_for_log(thd, str);
- if (!result)
- return NULL;
+ if (str->append(STRING_WITH_LEN(" NAME_CONST('")) ||
+ str->append(&m_name) ||
+ str->append(STRING_WITH_LEN("',")))
+ return true;
+ return append_value_for_log(thd, str) || str->append(')');
+}
- {
- StringBuffer<STRING_BUFFER_USUAL_SIZE> buf(result->charset());
- CHARSET_INFO *cs= thd->variables.character_set_client;
-
- buf.append('_');
- buf.append(result->charset()->csname);
- if (cs->escape_with_backslash_is_dangerous)
- buf.append(' ');
- append_query_string(cs, &buf, result->ptr(), result->length(),
- thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES);
- buf.append(" COLLATE '");
- buf.append(item->collation.collation->name);
- buf.append('\'');
- str->copy(buf);
-
- return str;
- }
- }
- case ROW_RESULT:
- default:
- return NULL;
- }
+bool Item_splocal::append_value_for_log(THD *thd, String *str)
+{
+ StringBuffer<STRING_BUFFER_USUAL_SIZE> str_value_holder(&my_charset_latin1);
+ Item *item= this_item();
+ String *str_value= item->type_handler()->print_item_value(thd, item,
+ &str_value_holder);
+ return str_value ?
+ str->append(*str_value) :
+ str->append(STRING_WITH_LEN("NULL"));
}
-bool Item_splocal::append_for_log(THD *thd, String *str)
+bool Item_splocal_row_field::append_for_log(THD *thd, String *str)
{
if (fix_fields(thd, NULL))
return true;
@@ -164,15 +140,11 @@ bool Item_splocal::append_for_log(THD *thd, String *str)
if (str->append(STRING_WITH_LEN(" NAME_CONST('")) ||
str->append(&m_name) ||
+ str->append(".") ||
+ str->append(&m_field_name) ||
str->append(STRING_WITH_LEN("',")))
return true;
-
- StringBuffer<STRING_BUFFER_USUAL_SIZE> str_value_holder(&my_charset_latin1);
- String *str_value= sp_get_item_value(thd, this_item(), &str_value_holder);
- if (str_value)
- return str->append(*str_value) || str->append(')');
- else
- return str->append(STRING_WITH_LEN("NULL)"));
+ return append_value_for_log(thd, str) || str->append(')');
}
@@ -262,12 +234,14 @@ sp_get_flags_for_command(LEX *lex)
flags= sp_head::CONTAINS_DYNAMIC_SQL;
break;
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
if (lex->tmp_table())
flags= 0;
else
flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
break;
case SQLCOM_DROP_TABLE:
+ case SQLCOM_DROP_SEQUENCE:
if (lex->tmp_table())
flags= 0;
else
@@ -286,6 +260,7 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_CREATE_USER:
case SQLCOM_CREATE_ROLE:
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_ALTER_SEQUENCE:
case SQLCOM_ALTER_USER:
case SQLCOM_GRANT:
case SQLCOM_GRANT_ROLE:
@@ -368,14 +343,20 @@ sp_get_flags_for_command(LEX *lex)
*/
Item *
-sp_prepare_func_item(THD* thd, Item **it_addr)
+sp_prepare_func_item(THD* thd, Item **it_addr, uint cols)
{
DBUG_ENTER("sp_prepare_func_item");
+ if (!(*it_addr)->fixed &&
+ (*it_addr)->fix_fields(thd, it_addr))
+ {
+ DBUG_PRINT("info", ("fix_fields() failed"));
+ DBUG_RETURN(NULL);
+ }
it_addr= (*it_addr)->this_item_addr(thd, it_addr);
- if (!(*it_addr)->fixed &&
- ((*it_addr)->fix_fields(thd, it_addr) ||
- (*it_addr)->check_cols(1)))
+ if ((!(*it_addr)->fixed &&
+ (*it_addr)->fix_fields(thd, it_addr)) ||
+ (*it_addr)->check_cols(cols))
{
DBUG_PRINT("info", ("fix_fields() failed"));
DBUG_RETURN(NULL);
@@ -398,7 +379,8 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
*/
bool
-sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
+sp_eval_expr(THD *thd, Item *result_item, Field *result_field,
+ Item **expr_item_ptr)
{
Item *expr_item;
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
@@ -411,10 +393,22 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
if (!*expr_item_ptr)
goto error;
- if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
+ if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr,
+ result_item ? result_item->cols() : 1)))
goto error;
/*
+ expr_item is now fixed, it's safe to call cmp_type()
+ If result_item is NULL, then we're setting the RETURN value.
+ */
+ if ((!result_item || result_item->cmp_type() != ROW_RESULT) &&
+ expr_item->cmp_type() == ROW_RESULT)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
+ goto error;
+ }
+
+ /*
Set THD flags to emit warnings/errors in case of overflow/type errors
during saving the item into the field.
@@ -461,42 +455,14 @@ error:
*/
sp_name::sp_name(const MDL_key *key, char *qname_buff)
+ :Database_qualified_name(key->db_name(), key->db_name_length(),
+ key->name(), key->name_length()),
+ m_explicit_name(false)
{
- m_db.str= (char*)key->db_name();
- m_db.length= key->db_name_length();
- m_name.str= (char*)key->name();
- m_name.length= key->name_length();
- m_qname.str= qname_buff;
if (m_db.length)
- {
strxmov(qname_buff, m_db.str, ".", m_name.str, NullS);
- m_qname.length= m_db.length + 1 + m_name.length;
- }
else
- {
strmov(qname_buff, m_name.str);
- m_qname.length= m_name.length;
- }
- m_explicit_name= false;
-}
-
-
-/**
- Init the qualified name from the db and name.
-*/
-void
-sp_name::init_qname(THD *thd)
-{
- const uint dot= !!m_db.length;
- /* m_qname format: [database + dot] + name + '\0' */
- m_qname.length= m_db.length + dot + m_name.length;
- if (!(m_qname.str= (char*) thd->alloc(m_qname.length + 1)))
- return;
- sprintf(m_qname.str, "%.*s%.*s%.*s",
- (int) m_db.length, (m_db.length ? m_db.str : ""),
- dot, ".",
- (int) m_name.length, m_name.str);
- DBUG_ASSERT(ok_for_lower_case_names(m_db.str));
}
@@ -514,7 +480,7 @@ sp_name::init_qname(THD *thd)
*/
bool
-check_routine_name(LEX_STRING *ident)
+check_routine_name(LEX_CSTRING *ident)
{
DBUG_ASSERT(ident);
DBUG_ASSERT(ident->str);
@@ -574,14 +540,32 @@ sp_head::operator delete(void *ptr, size_t size) throw()
}
-sp_head::sp_head()
+sp_head::sp_head(stored_procedure_type type)
:Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP),
+ Database_qualified_name(&null_clex_str, &null_clex_str),
+ m_type(type),
m_flags(0),
+ m_explicit_name(false),
+ /*
+ FIXME: the only use case when name is NULL is events, and it should
+ be rewritten soon. Remove the else part and replace 'if' with
+ an assert when this is done.
+ */
+ m_qname(null_clex_str),
+ m_params(null_clex_str),
+ m_body(null_clex_str),
+ m_body_utf8(null_clex_str),
+ m_defstr(null_clex_str),
m_sp_cache_version(0),
m_creation_ctx(0),
unsafe_flags(0),
+ m_created(0),
+ m_modified(0),
m_recursion_level(0),
m_next_cached_sp(0),
+ m_param_begin(NULL),
+ m_param_end(NULL),
+ m_body_begin(NULL),
m_cont_level(0)
{
m_first_instance= this;
@@ -589,25 +573,17 @@ sp_head::sp_head()
m_last_cached_sp= this;
m_return_field_def.charset = NULL;
- /*
- FIXME: the only use case when name is NULL is events, and it should
- be rewritten soon. Remove the else part and replace 'if' with
- an assert when this is done.
- */
- m_db= m_name= m_qname= null_lex_str;
DBUG_ENTER("sp_head::sp_head");
m_backpatch.empty();
+ m_backpatch_goto.empty();
m_cont_backpatch.empty();
m_lex.empty();
my_hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
my_hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key,
0, 0);
- m_body_utf8.str= NULL;
- m_body_utf8.length= 0;
-
DBUG_VOID_RETURN;
}
@@ -629,33 +605,6 @@ sp_head::init(LEX *lex)
lex->trg_table_fields.empty();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8, MYF(0));
- m_param_begin= NULL;
- m_param_end= NULL;
-
- m_body_begin= NULL ;
-
- m_qname.str= NULL;
- m_qname.length= 0;
-
- m_explicit_name= false;
-
- m_db.str= NULL;
- m_db.length= 0;
-
- m_name.str= NULL;
- m_name.length= 0;
-
- m_params.str= NULL;
- m_params.length= 0;
-
- m_body.str= NULL;
- m_body.length= 0;
-
- m_defstr.str= NULL;
- m_defstr.length= 0;
-
- m_return_field_def.charset= NULL;
-
DBUG_VOID_RETURN;
}
@@ -680,13 +629,7 @@ sp_head::init_sp_name(THD *thd, sp_name *spname)
m_explicit_name= spname->m_explicit_name;
- if (spname->m_qname.length == 0)
- spname->init_qname(thd);
-
- m_qname.length= spname->m_qname.length;
- m_qname.str= (char*) memdup_root(thd->mem_root,
- spname->m_qname.str,
- spname->m_qname.length + 1);
+ spname->make_qname(thd, &m_qname);
DBUG_VOID_RETURN;
}
@@ -744,58 +687,6 @@ sp_head::set_stmt_end(THD *thd)
}
-static TYPELIB *
-create_typelib(MEM_ROOT *mem_root, Column_definition *field_def, List<String> *src)
-{
- TYPELIB *result= NULL;
- CHARSET_INFO *cs= field_def->charset;
- DBUG_ENTER("create_typelib");
-
- if (src->elements)
- {
- result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
- result->count= src->elements;
- result->name= "";
- if (!(result->type_names=(const char **)
- alloc_root(mem_root,(sizeof(char *)+sizeof(int))*(result->count+1))))
- DBUG_RETURN(0);
- result->type_lengths= (uint*)(result->type_names + result->count+1);
- List_iterator<String> it(*src);
- String conv;
- for (uint i=0; i < result->count; i++)
- {
- uint32 dummy;
- uint length;
- String *tmp= it++;
-
- if (String::needs_conversion(tmp->length(), tmp->charset(),
- cs, &dummy))
- {
- uint cnv_errs;
- conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
-
- length= conv.length();
- result->type_names[i]= (char*) strmake_root(mem_root, conv.ptr(),
- length);
- }
- else
- {
- length= tmp->length();
- result->type_names[i]= strmake_root(mem_root, tmp->ptr(), length);
- }
-
- // Strip trailing spaces.
- length= cs->cset->lengthsp(cs, result->type_names[i], length);
- result->type_lengths[i]= length;
- ((uchar *)result->type_names[i])[length]= '\0';
- }
- result->type_names[result->count]= 0;
- result->type_lengths[result->count]= 0;
- }
- DBUG_RETURN(result);
-}
-
-
sp_head::~sp_head()
{
LEX *lex;
@@ -841,10 +732,11 @@ sp_head::~sp_head()
*/
Field *
-sp_head::create_result_field(uint field_max_length, const char *field_name,
+sp_head::create_result_field(uint field_max_length, const LEX_CSTRING *field_name,
TABLE *table)
{
Field *field;
+ LEX_CSTRING name;
DBUG_ENTER("sp_head::create_result_field");
@@ -887,11 +779,13 @@ sp_head::create_result_field(uint field_max_length, const char *field_name,
(m_return_field_def.pack_flag &
(FIELDFLAG_BLOB|FIELDFLAG_GEOM))));
+ if (field_name)
+ name= *field_name;
+ else
+ name= m_name;
field= m_return_field_def.make_field(table->s, /* TABLE_SHARE ptr */
table->in_use->mem_root,
- field_name ?
- field_name :
- (const char *) m_name.str);
+ &name);
field->vcol_info= m_return_field_def.vcol_info;
if (field)
@@ -1265,11 +1159,10 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
/* Discard the initial part of executing routines. */
thd->profiling.discard_current_query();
#endif
+ sp_instr *i;
DEBUG_SYNC(thd, "sp_head_execute_before_loop");
do
{
- sp_instr *i;
-
#if defined(ENABLED_PROFILING)
/*
Treat each "instr" of a routine as discrete unit that could be profiled.
@@ -1429,6 +1322,13 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
da->opt_clear_warning_info(thd->query_id);
da->copy_sql_conditions_from_wi(thd, &sp_wi);
da->remove_marked_sql_conditions();
+ if (i != NULL)
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_SP_STACK_TRACE,
+ ER_THD(thd, ER_SP_STACK_TRACE),
+ i->m_lineno,
+ m_qname.str != NULL ? m_qname.str :
+ "anonymous block");
}
}
@@ -1450,7 +1350,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
NULL. In this case, mysql_change_db() would generate an error.
*/
- err_status|= mysql_change_db(thd, &saved_cur_db_name, TRUE);
+ err_status|= mysql_change_db(thd, (LEX_CSTRING*) &saved_cur_db_name, TRUE);
}
m_flags&= ~IS_INVOKED;
DBUG_PRINT("info",
@@ -1510,9 +1410,9 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
Security_context **save_ctx)
{
*save_ctx= 0;
- if (sp->m_chistics->suid != SP_IS_NOT_SUID &&
- sp->m_security_ctx.change_security_context(thd, &sp->m_definer_user,
- &sp->m_definer_host,
+ if (sp->suid() != SP_IS_NOT_SUID &&
+ sp->m_security_ctx.change_security_context(thd, &sp->m_definer.user,
+ &sp->m_definer.host,
&sp->m_db,
save_ctx))
return TRUE;
@@ -1542,6 +1442,41 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
/**
+ Create rcontext using the routine security.
+ This is important for sql_mode=ORACLE to make sure that the invoker has
+ access to the tables mentioned in the %TYPE references.
+
+ In non-Oracle sql_modes we do not need access to any tables,
+ so we can omit the security context switch for performance purposes.
+
+ @param thd
+ @param sphead
+ @param is_proc
+ @param root_pctx
+ @param ret_value
+ @retval NULL - error (access denided or EOM)
+ @retval !NULL - success (the invoker has rights to all %TYPE tables)
+*/
+sp_rcontext *sp_head::rcontext_create(THD *thd, bool is_proc, Field *ret_value)
+{
+ bool has_column_type_refs= m_flags & HAS_COLUMN_TYPE_REFS;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ Security_context *save_security_ctx;
+ if (has_column_type_refs &&
+ set_routine_security_ctx(thd, this, is_proc, &save_security_ctx))
+ return NULL;
+#endif
+ sp_rcontext *res= sp_rcontext::create(thd, m_pcont, ret_value,
+ has_column_type_refs);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (has_column_type_refs)
+ m_security_ctx.restore_security_context(thd, save_security_ctx);
+#endif
+ return res;
+}
+
+
+/**
Execute trigger stored program.
- changes security context for triggers
@@ -1569,8 +1504,8 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
bool
sp_head::execute_trigger(THD *thd,
- const LEX_STRING *db_name,
- const LEX_STRING *table_name,
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name,
GRANT_INFO *grant_info)
{
sp_rcontext *octx = thd->spcont;
@@ -1587,10 +1522,10 @@ sp_head::execute_trigger(THD *thd,
Security_context *save_ctx= NULL;
- if (m_chistics->suid != SP_IS_NOT_SUID &&
+ if (suid() != SP_IS_NOT_SUID &&
m_security_ctx.change_security_context(thd,
- &m_definer_user,
- &m_definer_host,
+ &m_definer.user,
+ &m_definer.host,
&m_db,
&save_ctx))
DBUG_RETURN(TRUE);
@@ -1638,7 +1573,8 @@ sp_head::execute_trigger(THD *thd,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL)))
+ if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL,
+ m_flags & HAS_COLUMN_TYPE_REFS)))
{
err_status= TRUE;
goto err_with_cleanup;
@@ -1735,7 +1671,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
invoking query properly.
*/
my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0),
- "FUNCTION", m_qname.str, m_pcont->context_var_count(), argcount);
+ "FUNCTION", ErrConvDQName(this).ptr(),
+ m_pcont->context_var_count(), argcount);
DBUG_RETURN(TRUE);
}
/*
@@ -1752,7 +1689,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= sp_rcontext::create(thd, m_pcont, return_value_fld)))
+ if (!(nctx= rcontext_create(thd, false, return_value_fld)))
{
thd->restore_active_arena(&call_arena, &backup_arena);
err_status= TRUE;
@@ -1809,9 +1746,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
if (arg_no)
binlog_buf.append(',');
- str_value= sp_get_item_value(thd, nctx->get_item(arg_no),
- &str_value_holder);
-
+ Item *item= nctx->get_item(arg_no);
+ str_value= item->type_handler()->print_item_value(thd, item,
+ &str_value_holder);
if (str_value)
binlog_buf.append(*str_value);
else
@@ -1959,7 +1896,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (args->elements != params)
{
my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "PROCEDURE",
- m_qname.str, params, args->elements);
+ ErrConvDQName(this).ptr(), params, args->elements);
DBUG_RETURN(TRUE);
}
@@ -1967,7 +1904,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (! octx)
{
/* Create a temporary old context. */
- if (!(octx= sp_rcontext::create(thd, m_pcont, NULL)))
+ if (!(octx= rcontext_create(thd, true, NULL)))
{
DBUG_PRINT("error", ("Could not create octx"));
DBUG_RETURN(TRUE);
@@ -1982,7 +1919,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont->callers_arena= thd;
}
- if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL)))
+ if (!(nctx= rcontext_create(thd, true, NULL)))
{
delete nctx; /* Delete nctx if it was init() that failed. */
thd->spcont= save_spcont;
@@ -2017,7 +1954,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!srp)
{
- my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str);
+ my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, ErrConvDQName(this).ptr());
err_status= TRUE;
break;
}
@@ -2162,8 +2099,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
out_param_info->db_name= m_db.str;
out_param_info->table_name= m_name.str;
out_param_info->org_table_name= m_name.str;
- out_param_info->col_name= spvar->name.str;
- out_param_info->org_col_name= spvar->name.str;
+ out_param_info->col_name= spvar->name;
+ out_param_info->org_col_name= spvar->name;
srp->set_out_param_info(out_param_info);
}
@@ -2207,34 +2144,23 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
*/
bool
-sp_head::reset_lex(THD *thd)
+sp_head::reset_lex(THD *thd, sp_lex_local *sublex)
{
DBUG_ENTER("sp_head::reset_lex");
- LEX *sublex;
LEX *oldlex= thd->lex;
- sublex= new (thd->mem_root)st_lex_local;
- if (sublex == 0)
- DBUG_RETURN(TRUE);
-
- thd->lex= sublex;
- (void)m_lex.push_front(oldlex);
-
- /* Reset most stuff. */
- lex_start(thd);
+ thd->set_local_lex(sublex);
- /* And keep the SP stuff too */
- sublex->sphead= oldlex->sphead;
- sublex->spcont= oldlex->spcont;
- /* And trigger related stuff too */
- sublex->trg_chistics= oldlex->trg_chistics;
- sublex->trg_table_fields.empty();
- sublex->sp_lex_in_use= FALSE;
+ DBUG_RETURN(m_lex.push_front(oldlex));
+}
- /* Reset part of parser state which needs this. */
- thd->m_parser_state->m_yacc.reset_before_substatement();
- DBUG_RETURN(FALSE);
+bool
+sp_head::reset_lex(THD *thd)
+{
+ DBUG_ENTER("sp_head::reset_lex");
+ sp_lex_local *sublex= new (thd->mem_root) sp_lex_local(thd, thd->lex);
+ DBUG_RETURN(sublex ? reset_lex(thd, sublex) : true);
}
@@ -2242,6 +2168,8 @@ sp_head::reset_lex(THD *thd)
Restore lex during parsing, after we have parsed a sub statement.
@param thd Thread handle
+ @param oldlex The upper level lex we're near to restore to
+ @param sublex The local lex we're near to restore from
@return
@retval TRUE failure
@@ -2249,23 +2177,17 @@ sp_head::reset_lex(THD *thd)
*/
bool
-sp_head::restore_lex(THD *thd)
+sp_head::merge_lex(THD *thd, LEX *oldlex, LEX *sublex)
{
- DBUG_ENTER("sp_head::restore_lex");
- LEX *sublex= thd->lex;
- LEX *oldlex;
+ DBUG_ENTER("sp_head::merge_lex");
sublex->set_trg_event_type_for_tables();
- oldlex= (LEX *)m_lex.pop();
- if (! oldlex)
- DBUG_RETURN(FALSE); // Nothing to restore
-
oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
/* If this substatement is unsafe, the entire routine is too. */
- DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags: 0x%x",
- thd->lex->get_stmt_unsafe_flags()));
+ DBUG_PRINT("info", ("sublex->get_stmt_unsafe_flags: 0x%x",
+ sublex->get_stmt_unsafe_flags()));
unsafe_flags|= sublex->get_stmt_unsafe_flags();
/*
@@ -2287,13 +2209,6 @@ sp_head::restore_lex(THD *thd)
/* Merge lists of PS parameters. */
oldlex->param_list.append(&sublex->param_list);
- if (! sublex->sp_lex_in_use)
- {
- sublex->sphead= NULL;
- lex_end(sublex);
- delete sublex;
- }
- thd->lex= oldlex;
DBUG_RETURN(FALSE);
}
@@ -2301,7 +2216,8 @@ sp_head::restore_lex(THD *thd)
Put the instruction on the backpatch list, associated with the label.
*/
int
-sp_head::push_backpatch(THD *thd, sp_instr *i, sp_label *lab)
+sp_head::push_backpatch(THD *thd, sp_instr *i, sp_label *lab,
+ List<bp_t> *list, backpatch_instr_type itype)
{
bp_t *bp= (bp_t *) thd->alloc(sizeof(bp_t));
@@ -2309,7 +2225,45 @@ sp_head::push_backpatch(THD *thd, sp_instr *i, sp_label *lab)
return 1;
bp->lab= lab;
bp->instr= i;
- return m_backpatch.push_front(bp);
+ bp->instr_type= itype;
+ return list->push_front(bp);
+}
+
+int
+sp_head::push_backpatch(THD *thd, sp_instr *i, sp_label *lab)
+{
+ return push_backpatch(thd, i, lab, &m_backpatch, GOTO);
+}
+
+int
+sp_head::push_backpatch_goto(THD *thd, sp_pcontext *ctx, sp_label *lab)
+{
+ uint ip= instructions();
+
+ /*
+ Add cpop/hpop : they will be removed or updated later if target is in
+ the same block or not
+ */
+ sp_instr_hpop *hpop= new (thd->mem_root) sp_instr_hpop(ip++, ctx, 0);
+ if (hpop == NULL || add_instr(hpop))
+ return true;
+ if (push_backpatch(thd, hpop, lab, &m_backpatch_goto, HPOP))
+ return true;
+
+ sp_instr_cpop *cpop= new (thd->mem_root) sp_instr_cpop(ip++, ctx, 0);
+ if (cpop == NULL || add_instr(cpop))
+ return true;
+ if (push_backpatch(thd, cpop, lab, &m_backpatch_goto, CPOP))
+ return true;
+
+ // Add jump with ip=0. IP will be updated when label is found.
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(ip, ctx);
+ if (i == NULL || add_instr(i))
+ return true;
+ if (push_backpatch(thd, i, lab, &m_backpatch_goto, GOTO))
+ return true;
+
+ return false;
}
/**
@@ -2336,44 +2290,98 @@ sp_head::backpatch(sp_label *lab)
DBUG_VOID_RETURN;
}
-/**
- Prepare an instance of Column_definition for field creation
- (fill all necessary attributes).
-
- @param[in] thd Thread handle
- @param[in] lex Yacc parsing context
- @param[out] field_def An instance of create_field to be filled
+void
+sp_head::backpatch_goto(THD *thd, sp_label *lab,sp_label *lab_begin_block)
+{
+ bp_t *bp;
+ uint dest= instructions();
+ List_iterator<bp_t> li(m_backpatch_goto);
- @retval
- FALSE on success
- @retval
- TRUE on error
-*/
+ DBUG_ENTER("sp_head::backpatch_goto");
+ while ((bp= li++))
+ {
+ if (bp->instr->m_ip < lab_begin_block->ip || bp->instr->m_ip > lab->ip)
+ {
+ /*
+ Update only jump target from the beginning of the block where the
+ label is defined.
+ */
+ continue;
+ }
+ if (my_strcasecmp(system_charset_info,
+ bp->lab->name.str,
+ lab->name.str) == 0)
+ {
+ if (bp->instr_type == GOTO)
+ {
+ DBUG_PRINT("info",
+ ("backpatch_goto: (m_ip %d, label 0x%lx <%s>) to dest %d",
+ bp->instr->m_ip, (ulong) lab, lab->name.str, dest));
+ bp->instr->backpatch(dest, lab->ctx);
+ // Jump resolved, remove from the list
+ li.remove();
+ continue;
+ }
+ if (bp->instr_type == CPOP)
+ {
+ int n= lab->ctx->diff_cursors(lab_begin_block->ctx, true);
+ if (n == 0)
+ {
+ // Remove cpop instr
+ replace_instr_to_nop(thd,bp->instr->m_ip);
+ }
+ else
+ {
+ // update count of cpop
+ static_cast<sp_instr_cpop*>(bp->instr)->update_count(n);
+ n= 1;
+ }
+ li.remove();
+ continue;
+ }
+ if (bp->instr_type == HPOP)
+ {
+ int n= lab->ctx->diff_handlers(lab_begin_block->ctx, true);
+ if (n == 0)
+ {
+ // Remove hpop instr
+ replace_instr_to_nop(thd,bp->instr->m_ip);
+ }
+ else
+ {
+ // update count of cpop
+ static_cast<sp_instr_hpop*>(bp->instr)->update_count(n);
+ n= 1;
+ }
+ li.remove();
+ continue;
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
bool
-sp_head::fill_field_definition(THD *thd, LEX *lex,
- Column_definition *field_def)
+sp_head::check_unresolved_goto()
{
- uint unused1= 0;
-
- if (field_def->check(thd))
- return TRUE;
-
- if (field_def->interval_list.elements)
- field_def->interval= create_typelib(mem_root, field_def,
- &field_def->interval_list);
-
- sp_prepare_create_field(thd, field_def);
-
- if (prepare_create_field(field_def, &unused1, HA_CAN_GEOMETRY))
+ DBUG_ENTER("sp_head::check_unresolved_goto");
+ bool has_unresolved_label=false;
+ if (m_backpatch_goto.elements > 0)
{
- return TRUE;
+ List_iterator_fast<bp_t> li(m_backpatch_goto);
+ bp_t *bp;
+ while ((bp= li++))
+ {
+ if ((bp->instr_type == GOTO))
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "GOTO", bp->lab->name.str);
+ has_unresolved_label=true;
+ }
+ }
}
-
- return FALSE;
+ DBUG_RETURN(has_unresolved_label);
}
-
int
sp_head::new_cont_backpatch(sp_instr_opt_meta *i)
{
@@ -2409,20 +2417,43 @@ sp_head::do_cont_backpatch()
}
}
+
+bool
+sp_head::sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext)
+{
+ for (uint i= 0; i < pcontext->frame_cursor_count(); i++)
+ {
+ const sp_pcursor *c= pcontext->get_cursor_by_local_frame_offset(i);
+ sp_instr_cpush *instr= new (thd->mem_root)
+ sp_instr_cpush(instructions(), pcontext, c->lex(),
+ pcontext->cursor_offset() + i);
+ if (instr == NULL || add_instr(instr))
+ return true;
+ }
+ return false;
+}
+
+
+void
+sp_head::set_chistics(const st_sp_chistics &chistics)
+{
+ m_chistics.set(chistics);
+ if (m_chistics.comment.length == 0)
+ m_chistics.comment.str= 0;
+ else
+ m_chistics.comment.str= strmake_root(mem_root,
+ m_chistics.comment.str,
+ m_chistics.comment.length);
+}
+
+
void
sp_head::set_info(longlong created, longlong modified,
- st_sp_chistics *chistics, sql_mode_t sql_mode)
+ const st_sp_chistics &chistics, sql_mode_t sql_mode)
{
m_created= created;
m_modified= modified;
- m_chistics= (st_sp_chistics *) memdup_root(mem_root, (char*) chistics,
- sizeof(*chistics));
- if (m_chistics->comment.length == 0)
- m_chistics->comment.str= 0;
- else
- m_chistics->comment.str= strmake_root(mem_root,
- m_chistics->comment.str,
- m_chistics->comment.length);
+ set_chistics(chistics);
m_sql_mode= sql_mode;
}
@@ -2431,13 +2462,13 @@ void
sp_head::set_definer(const char *definer, uint definerlen)
{
char user_name_holder[USERNAME_LENGTH + 1];
- LEX_STRING user_name= { user_name_holder, USERNAME_LENGTH };
+ LEX_CSTRING user_name= { user_name_holder, USERNAME_LENGTH };
char host_name_holder[HOSTNAME_LENGTH + 1];
- LEX_STRING host_name= { host_name_holder, HOSTNAME_LENGTH };
+ LEX_CSTRING host_name= { host_name_holder, HOSTNAME_LENGTH };
- if (parse_user(definer, definerlen, user_name.str, &user_name.length,
- host_name.str, &host_name.length) &&
+ if (parse_user(definer, definerlen, user_name_holder, &user_name.length,
+ host_name_holder, &host_name.length) &&
user_name.length && !host_name.length)
{
// 'user@' -> 'user@%'
@@ -2449,17 +2480,6 @@ sp_head::set_definer(const char *definer, uint definerlen)
void
-sp_head::set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name)
-{
- m_definer_user.str= strmake_root(mem_root, user_name->str, user_name->length);
- m_definer_user.length= user_name->length;
-
- m_definer_host.str= strmake_root(mem_root, host_name->str, host_name->length);
- m_definer_host.length= host_name->length;
-}
-
-
-void
sp_head::reset_thd_mem_root(THD *thd)
{
DBUG_ENTER("sp_head::reset_thd_mem_root");
@@ -2527,9 +2547,9 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
*full_access= ((!check_table_access(thd, SELECT_ACL, &tables, FALSE,
1, TRUE) &&
(tables.grant.privilege & SELECT_ACL) != 0) ||
- (!strcmp(sp->m_definer_user.str,
+ (!strcmp(sp->m_definer.user.str,
thd->security_ctx->priv_user) &&
- !strcmp(sp->m_definer_host.str,
+ !strcmp(sp->m_definer.host.str,
thd->security_ctx->priv_host)));
if (!*full_access)
return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str,
@@ -2627,7 +2647,7 @@ sp_head::show_create_routine(THD *thd, int type)
Protocol *protocol= thd->protocol;
List<Item> fields;
- LEX_STRING sql_mode;
+ LEX_CSTRING sql_mode;
bool full_access;
MEM_ROOT *mem_root= thd->mem_root;
@@ -2732,10 +2752,66 @@ int sp_head::add_instr(sp_instr *instr)
entire stored procedure, as their life span is equal.
*/
instr->mem_root= &main_mem_root;
+ instr->m_lineno= m_thd->m_parser_state->m_lip.yylineno;
return insert_dynamic(&m_instr, (uchar*)&instr);
}
+bool sp_head::add_instr_jump(THD *thd, sp_pcontext *spcont)
+{
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(instructions(), spcont);
+ return i == NULL || add_instr(i);
+}
+
+
+bool sp_head::add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest)
+{
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(instructions(),
+ spcont, dest);
+ return i == NULL || add_instr(i);
+}
+
+
+bool sp_head::add_instr_jump_forward_with_backpatch(THD *thd,
+ sp_pcontext *spcont,
+ sp_label *lab)
+{
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(instructions(), spcont);
+ if (i == NULL || add_instr(i))
+ return true;
+ push_backpatch(thd, i, lab);
+ return false;
+}
+
+
+/*
+ Replace an instruction at position to "no operation".
+
+ @param thd - use mem_root of this THD for "new".
+ @param ip - position of the operation
+ @returns - true on error, false on success
+
+ When we need to remove an instruction that during compilation
+ appeared to be useless (typically as useless jump), we replace
+ it to a jump to exactly the next instruction.
+ Such jumps are later removed during sp_head::optimize().
+
+ QQ: Perhaps we need a dedicated sp_instr_nop for this purpose.
+*/
+bool sp_head::replace_instr_to_nop(THD *thd, uint ip)
+{
+ sp_instr *instr= get_instr(ip);
+ sp_instr_jump *nop= new (thd->mem_root) sp_instr_jump(instr->m_ip,
+ instr->m_ctx,
+ instr->m_ip + 1);
+ if (!nop)
+ return true;
+ delete instr;
+ set_dynamic(&m_instr, (uchar *) &nop, ip);
+ return false;
+}
+
+
/**
Do some minimal optimization of the code:
-# Mark used instructions
@@ -2893,7 +2969,7 @@ sp_head::show_routine_code(THD *thd)
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, tmp);
}
protocol->prepare_for_resend();
- protocol->store((longlong)ip);
+ protocol->store_long(ip);
buffer.set("", 0, system_charset_info);
i->print(&buffer);
@@ -3083,6 +3159,25 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
}
+int sp_lex_keeper::cursor_reset_lex_and_exec_core(THD *thd, uint *nextp,
+ bool open_tables,
+ sp_instr *instr)
+{
+ Query_arena *old_arena= thd->stmt_arena;
+ /*
+ Get the Query_arena from the cursor statement LEX, which contains
+ the free_list of the query, so new items (if any) are stored in
+ the right free_list, and we can cleanup after each cursor operation,
+ e.g. open or cursor_copy_struct (for cursor%ROWTYPE variables).
+ */
+ thd->stmt_arena= m_lex->query_arena();
+ int res= reset_lex_and_exec_core(thd, nextp, open_tables, instr);
+ cleanup_items(thd->stmt_arena->free_list);
+ thd->stmt_arena= old_arena;
+ return res;
+}
+
+
/*
sp_instr class functions
*/
@@ -3300,6 +3395,114 @@ sp_instr_set::print(String *str)
/*
+ sp_instr_set_field class functions
+*/
+
+int
+sp_instr_set_row_field::exec_core(THD *thd, uint *nextp)
+{
+ int res= thd->spcont->set_variable_row_field(thd, m_offset, m_field_offset,
+ &m_value);
+ if (res)
+ {
+ /* Failed to evaluate the value. Reset the variable to NULL. */
+ thd->spcont->set_variable_row_field_to_null(thd, m_offset, m_field_offset);
+ }
+ delete_explain_query(thd->lex);
+ *nextp= m_ip + 1;
+ return res;
+}
+
+
+void
+sp_instr_set_row_field::print(String *str)
+{
+ /* set name@offset[field_offset] ... */
+ int rsrv= SP_INSTR_UINT_MAXLEN + 6 + 6 + 3;
+ sp_variable *var= m_ctx->find_variable(m_offset);
+ DBUG_ASSERT(var);
+ DBUG_ASSERT(var->field_def.is_row());
+ const Column_definition *def=
+ var->field_def.row_field_definitions()->elem(m_field_offset);
+ DBUG_ASSERT(def);
+
+ rsrv+= var->name.length + def->field_name.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("set "));
+ str->qs_append(var->name.str, var->name.length);
+ str->qs_append('.');
+ str->qs_append(def->field_name.str, def->field_name.length);
+ str->qs_append('@');
+ str->qs_append(m_offset);
+ str->qs_append('[');
+ str->qs_append(m_field_offset);
+ str->qs_append(']');
+ str->qs_append(' ');
+ m_value->print(str, enum_query_type(QT_ORDINARY |
+ QT_ITEM_ORIGINAL_FUNC_NULLIF));
+}
+
+
+/*
+ sp_instr_set_field_by_name class functions
+*/
+
+int
+sp_instr_set_row_field_by_name::exec_core(THD *thd, uint *nextp)
+{
+ int res;
+ uint idx;
+ Item_field_row *row= (Item_field_row*) thd->spcont->get_item(m_offset);
+ if ((res= row->element_index_by_name(&idx, m_field_name)))
+ {
+ sp_variable *var= m_ctx->find_variable(m_offset);
+ my_error(ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD, MYF(0),
+ var->name.str, m_field_name.str);
+ goto error;
+ }
+ res= thd->spcont->set_variable_row_field(thd, m_offset, idx, &m_value);
+ if (res)
+ {
+ /* Failed to evaluate the value. Reset the variable to NULL. */
+ thd->spcont->set_variable_row_field_to_null(thd, m_offset, idx);
+ }
+error:
+ delete_explain_query(thd->lex);
+ *nextp= m_ip + 1;
+ return res;
+}
+
+
+void
+sp_instr_set_row_field_by_name::print(String *str)
+{
+ /* set name.field@offset["field"] ... */
+ int rsrv= SP_INSTR_UINT_MAXLEN + 6 + 6 + 3 + 2;
+ sp_variable *var= m_ctx->find_variable(m_offset);
+ DBUG_ASSERT(var);
+ DBUG_ASSERT(var->field_def.is_table_rowtype_ref() ||
+ var->field_def.is_cursor_rowtype_ref());
+
+ rsrv+= var->name.length + 2 * m_field_name.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("set "));
+ str->qs_append(var->name.str, var->name.length);
+ str->qs_append('.');
+ str->qs_append(m_field_name.str, m_field_name.length);
+ str->qs_append('@');
+ str->qs_append(m_offset);
+ str->qs_append("[\"",2);
+ str->qs_append(m_field_name.str, m_field_name.length);
+ str->qs_append("\"]",2);
+ str->qs_append(' ');
+ m_value->print(str, enum_query_type(QT_ORDINARY |
+ QT_ITEM_ORIGINAL_FUNC_NULLIF));
+}
+
+
+/*
sp_instr_set_trigger_field class functions
*/
@@ -3524,8 +3727,21 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
That means, Diagnostics Area should be clean before its execution.
*/
- Diagnostics_area *da= thd->get_stmt_da();
- da->clear_warning_info(da->warning_info_id());
+ if (!(thd->variables.sql_mode & MODE_ORACLE))
+ {
+ /*
+ Don't clean warnings in ORACLE mode,
+ as they are needed for SQLCODE and SQLERRM:
+ BEGIN
+ SELECT a INTO a FROM t1;
+ RETURN 'No exception ' || SQLCODE || ' ' || SQLERRM;
+ EXCEPTION WHEN NO_DATA_FOUND THEN
+ RETURN 'Exception ' || SQLCODE || ' ' || SQLERRM;
+ END;
+ */
+ Diagnostics_area *da= thd->get_stmt_da();
+ da->clear_warning_info(da->warning_info_id());
+ }
/*
Change <next instruction pointer>, so that this will be the last
@@ -3552,7 +3768,7 @@ sp_instr_freturn::print(String *str)
if (str->reserve(1024+8+32)) // Add some for the expr. too
return;
str->qs_append(STRING_WITH_LEN("freturn "));
- str->qs_append((uint)m_type);
+ str->qs_append(m_type_handler->name().ptr());
str->qs_append(' ');
m_value->print(str, enum_query_type(QT_ORDINARY |
QT_ITEM_ORIGINAL_FUNC_NULLIF));
@@ -3726,7 +3942,7 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_cpush::execute");
- int ret= thd->spcont->push_cursor(thd, &m_lex_keeper, this);
+ int ret= thd->spcont->push_cursor(thd, &m_lex_keeper);
*nextp= m_ip+1;
@@ -3737,7 +3953,7 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
void
sp_instr_cpush::print(String *str)
{
- const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+ const LEX_CSTRING *cursor_name= m_ctx->find_cursor(m_cursor);
/* cpush name@offset */
uint rsrv= SP_INSTR_UINT_MAXLEN+7;
@@ -3806,19 +4022,7 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
else
{
sp_lex_keeper *lex_keeper= c->get_lex_keeper();
- Query_arena *old_arena= thd->stmt_arena;
-
- /*
- Get the Query_arena from the cpush instruction, which contains
- the free_list of the query, so new items (if any) are stored in
- the right free_list, and we can cleanup after each open.
- */
- thd->stmt_arena= c->get_instr();
- res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
- /* Cleanup the query's items */
- if (thd->stmt_arena->free_list)
- cleanup_items(thd->stmt_arena->free_list);
- thd->stmt_arena= old_arena;
+ res= lex_keeper->cursor_reset_lex_and_exec_core(thd, nextp, FALSE, this);
/* TODO: Assert here that we either have an error or a cursor */
}
DBUG_RETURN(res);
@@ -3837,7 +4041,7 @@ sp_instr_copen::exec_core(THD *thd, uint *nextp)
void
sp_instr_copen::print(String *str)
{
- const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+ const LEX_CSTRING *cursor_name= m_ctx->find_cursor(m_cursor);
/* copen name@offset */
uint rsrv= SP_INSTR_UINT_MAXLEN+7;
@@ -3879,7 +4083,7 @@ sp_instr_cclose::execute(THD *thd, uint *nextp)
void
sp_instr_cclose::print(String *str)
{
- const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+ const LEX_CSTRING *cursor_name= m_ctx->find_cursor(m_cursor);
/* cclose name@offset */
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
@@ -3922,7 +4126,7 @@ sp_instr_cfetch::print(String *str)
{
List_iterator_fast<sp_variable> li(m_varlist);
sp_variable *pv;
- const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+ const LEX_CSTRING *cursor_name= m_ctx->find_cursor(m_cursor);
/* cfetch name@offset vars... */
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
@@ -3951,6 +4155,84 @@ sp_instr_cfetch::print(String *str)
/*
+ sp_instr_cursor_copy_struct class functions
+*/
+
+/**
+ This methods processes cursor %ROWTYPE declarations, e.g.:
+ CURSOR cur IS SELECT * FROM t1;
+ rec cur%ROWTYPE;
+ and does the following:
+ - opens the cursor without copying data (materialization).
+ - copies the cursor structure to the associated %ROWTYPE variable.
+*/
+int
+sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_cursor_copy_struct::exec_core");
+ int ret= 0;
+ Item_field_row *row= (Item_field_row*) thd->spcont->get_item(m_var);
+ DBUG_ASSERT(row->type_handler() == &type_handler_row);
+
+ /*
+ Copy structure only once. If the cursor%ROWTYPE variable is declared
+ inside a LOOP block, it gets its structure on the first loop interation
+ and remembers the structure for all consequent loop iterations.
+ It we recreated the structure on every iteration, we would get
+ potential memory leaks, and it would be less efficient.
+ */
+ if (!row->arguments())
+ {
+ sp_cursor tmp(thd, &m_lex_keeper);
+ // Open the cursor without copying data
+ if (!(ret= tmp.open_view_structure_only(thd)))
+ {
+ Row_definition_list defs;
+ if (!(ret= tmp.export_structure(thd, &defs)))
+ {
+ /*
+ Create row elements on the caller arena.
+ It's the same arena that was used during sp_rcontext::create().
+ This puts cursor%ROWTYPE elements on the same mem_root
+ where explicit ROW elements and table%ROWTYPE reside.
+ */
+ Query_arena current_arena;
+ thd->set_n_backup_active_arena(thd->spcont->callers_arena, &current_arena);
+ row->row_create_items(thd, &defs);
+ thd->restore_active_arena(thd->spcont->callers_arena, &current_arena);
+ }
+ tmp.close(thd);
+ }
+ }
+ *nextp= m_ip + 1;
+ DBUG_RETURN(ret);
+}
+
+
+int
+sp_instr_cursor_copy_struct::execute(THD *thd, uint *nextp)
+{
+ DBUG_ENTER("sp_instr_cursor_copy_struct::execute");
+ int ret= m_lex_keeper.cursor_reset_lex_and_exec_core(thd, nextp, FALSE, this);
+ DBUG_RETURN(ret);
+}
+
+
+void
+sp_instr_cursor_copy_struct::print(String *str)
+{
+ sp_variable *var= m_ctx->find_variable(m_var);
+ const LEX_CSTRING *name= m_lex_keeper.cursor_name();
+ str->append(STRING_WITH_LEN("cursor_copy_struct "));
+ str->append(name);
+ str->append(' ');
+ str->append(&var->name);
+ str->append('@');
+ str->append_ulonglong(m_var);
+}
+
+
+/*
sp_instr_error class functions
*/
@@ -4114,7 +4396,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
{
SP_TABLE *tab;
- if (lex_for_tmp_check->sql_command == SQLCOM_DROP_TABLE &&
+ if ((lex_for_tmp_check->sql_command == SQLCOM_DROP_TABLE ||
+ lex_for_tmp_check->sql_command == SQLCOM_DROP_SEQUENCE) &&
lex_for_tmp_check->tmp_table())
return TRUE;
@@ -4178,7 +4461,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
{
if (!(tab= (SP_TABLE *)thd->calloc(sizeof(SP_TABLE))))
return FALSE;
- if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE &&
+ if ((lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE ||
+ lex_for_tmp_check->sql_command == SQLCOM_CREATE_SEQUENCE) &&
lex_for_tmp_check->query_tables == table &&
lex_for_tmp_check->tmp_table())
{
@@ -4310,3 +4594,154 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
return table;
}
+
+Item *sp_head::adjust_assignment_source(THD *thd, Item *val, Item *val2)
+{
+ return val ? val : val2 ? val2 : new (thd->mem_root) Item_null(thd);
+}
+
+/**
+ Helper action for a SET statement.
+ Used to push a SP local variable into the assignment list.
+
+ @param var_type the SP local variable
+ @param val the value being assigned to the variable
+
+ @return TRUE if error, FALSE otherwise.
+*/
+
+bool
+sp_head::set_local_variable(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv, Item *val, LEX *lex,
+ bool responsible_to_free_lex)
+{
+ if (!(val= adjust_assignment_source(thd, val, spv->default_value)))
+ return true;
+
+ sp_instr_set *sp_set= new (thd->mem_root)
+ sp_instr_set(instructions(), spcont,
+ spv->offset, val, lex,
+ responsible_to_free_lex);
+
+ return sp_set == NULL || add_instr(sp_set);
+}
+
+
+/**
+ Similar to set_local_variable(), but for ROW variable fields.
+*/
+bool
+sp_head::set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv, uint field_idx,
+ Item *val, LEX *lex)
+{
+ if (!(val= adjust_assignment_source(thd, val, NULL)))
+ return true;
+
+ sp_instr_set_row_field *sp_set= new (thd->mem_root)
+ sp_instr_set_row_field(instructions(),
+ spcont,
+ spv->offset,
+ field_idx, val,
+ lex, true);
+ return sp_set == NULL || add_instr(sp_set);
+}
+
+
+bool
+sp_head::set_local_variable_row_field_by_name(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv,
+ const LEX_CSTRING *field_name,
+ Item *val, LEX *lex)
+{
+ if (!(val= adjust_assignment_source(thd, val, NULL)))
+ return true;
+
+ sp_instr_set_row_field_by_name *sp_set=
+ new (thd->mem_root) sp_instr_set_row_field_by_name(instructions(),
+ spcont,
+ spv->offset,
+ *field_name,
+ val,
+ lex, true);
+ return sp_set == NULL || add_instr(sp_set);
+}
+
+
+bool sp_head::add_open_cursor(THD *thd, sp_pcontext *spcont, uint offset,
+ sp_pcontext *param_spcont,
+ List<sp_assignment_lex> *parameters)
+{
+ /*
+ The caller must make sure that the number of formal parameters matches
+ the number of actual parameters.
+ */
+ DBUG_ASSERT((param_spcont ? param_spcont->context_var_count() : 0) ==
+ (parameters ? parameters->elements : 0));
+
+ if (parameters &&
+ add_set_cursor_param_variables(thd, param_spcont, parameters))
+ return true;
+
+ sp_instr_copen *i= new (thd->mem_root)
+ sp_instr_copen(instructions(), spcont, offset);
+ return i == NULL || add_instr(i);
+}
+
+
+bool sp_head::add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont,
+ sp_variable *index,
+ const sp_pcursor *pcursor, uint coffset,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters)
+{
+ if (parameters &&
+ add_set_for_loop_cursor_param_variables(thd, pcursor->param_context(),
+ param_lex, parameters))
+ return true;
+
+ sp_instr *instr_copy_struct=
+ new (thd->mem_root) sp_instr_cursor_copy_struct(instructions(),
+ spcont, pcursor->lex(),
+ index->offset);
+ if (instr_copy_struct == NULL || add_instr(instr_copy_struct))
+ return true;
+
+ sp_instr_copen *instr_copen=
+ new (thd->mem_root) sp_instr_copen(instructions(), spcont, coffset);
+ if (instr_copen == NULL || add_instr(instr_copen))
+ return true;
+
+ sp_instr_cfetch *instr_cfetch=
+ new (thd->mem_root) sp_instr_cfetch(instructions(),
+ spcont, coffset);
+ if (instr_cfetch == NULL || add_instr(instr_cfetch))
+ return true;
+ instr_cfetch->add_to_varlist(index);
+ return false;
+}
+
+
+bool
+sp_head::add_set_for_loop_cursor_param_variables(THD *thd,
+ sp_pcontext *param_spcont,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters)
+{
+ DBUG_ASSERT(param_spcont->context_var_count() == parameters->argument_count());
+ for (uint idx= 0; idx < parameters->argument_count(); idx ++)
+ {
+ /*
+ param_lex is shared between multiple items (cursor parameters).
+ Only the last sp_instr_set is responsible for freeing param_lex.
+ See more comments in LEX::sp_for_loop_cursor_declarations in sql_lex.cc.
+ */
+ bool last= idx + 1 == parameters->argument_count();
+ sp_variable *spvar= param_spcont->get_context_variable(idx);
+ if (set_local_variable(thd, param_spcont,
+ spvar, parameters->arguments()[idx],
+ param_lex, last))
+ return true;
+ }
+ return false;
+}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 9f1745f2aab..1435bb460c3 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -107,39 +107,33 @@ protected:
/*************************************************************************/
-class sp_name : public Sql_alloc
+class sp_name : public Sql_alloc,
+ public Database_qualified_name
{
public:
-
- LEX_STRING m_db;
- LEX_STRING m_name;
- LEX_STRING m_qname;
bool m_explicit_name; /**< Prepend the db name? */
- sp_name(LEX_STRING db, LEX_STRING name, bool use_explicit_name)
- : m_db(db), m_name(name), m_explicit_name(use_explicit_name)
+ sp_name(const LEX_CSTRING *db, const LEX_CSTRING *name,
+ bool use_explicit_name)
+ : Database_qualified_name(db, name), m_explicit_name(use_explicit_name)
{
if (lower_case_table_names && m_db.str)
- m_db.length= my_casedn_str(files_charset_info, m_db.str);
- m_qname.str= 0;
- m_qname.length= 0;
+ m_db.length= my_casedn_str(files_charset_info, (char*) m_db.str);
}
- /** Create temporary sp_name object from MDL key. */
+ /** Create temporary sp_name object from MDL key. Store in qname_buff */
sp_name(const MDL_key *key, char *qname_buff);
- // Init. the qualified name from the db and name.
- void init_qname(THD *thd); // thd for memroot allocation
-
~sp_name()
{}
};
bool
-check_routine_name(LEX_STRING *ident);
+check_routine_name(LEX_CSTRING *ident);
-class sp_head :private Query_arena
+class sp_head :private Query_arena,
+ public Database_qualified_name
{
sp_head(const sp_head &); /**< Prevent use of these */
void operator=(sp_head &);
@@ -172,7 +166,11 @@ public:
b) because in CONTAINS SQL case they don't provide enough
information anyway.
*/
- MODIFIES_DATA= 4096
+ MODIFIES_DATA= 4096,
+ /*
+ Marks routines that have column type references: DECLARE a t1.a%TYPE;
+ */
+ HAS_COLUMN_TYPE_REFS= 8192
};
stored_procedure_type m_type;
@@ -181,19 +179,30 @@ public:
Column_definition m_return_field_def; /**< This is used for FUNCTIONs only. */
const char *m_tmp_query; ///< Temporary pointer to sub query string
- st_sp_chistics *m_chistics;
+private:
+ /*
+ Private to guarantee that m_chistics.comment is properly set to:
+ - a string which is alloced on this->mem_root
+ - or (NULL,0)
+ set_chistics() makes sure this.
+ */
+ Sp_chistics m_chistics;
+public:
sql_mode_t m_sql_mode; ///< For SHOW CREATE and execution
- LEX_STRING m_qname; ///< db.name
- bool m_explicit_name; ///< Prepend the db name? */
- LEX_STRING m_db;
- LEX_STRING m_name;
- LEX_STRING m_params;
- LEX_STRING m_body;
- LEX_STRING m_body_utf8;
- LEX_STRING m_defstr;
- LEX_STRING m_definer_user;
- LEX_STRING m_definer_host;
-
+ bool m_explicit_name; /**< Prepend the db name? */
+ LEX_CSTRING m_qname; ///< db.name
+ LEX_CSTRING m_params;
+ LEX_CSTRING m_body;
+ LEX_CSTRING m_body_utf8;
+ LEX_CSTRING m_defstr;
+ AUTHID m_definer;
+
+ const st_sp_chistics &chistics() const { return m_chistics; }
+ const LEX_CSTRING &comment() const { return m_chistics.comment; }
+ void set_suid(enum_sp_suid_behaviour suid) { m_chistics.suid= suid; }
+ enum_sp_suid_behaviour suid() const { return m_chistics.suid; }
+ bool detistic() const { return m_chistics.detistic; }
+ enum_sp_data_access daccess() const { return m_chistics.daccess; }
/**
Is this routine being executed?
*/
@@ -210,6 +219,9 @@ public:
{
m_sp_cache_version= version_arg;
}
+
+ sp_rcontext *rcontext_create(THD *thd, bool is_proc, Field *ret_value);
+
private:
/**
Version of the stored routine cache at the moment when the
@@ -305,7 +317,7 @@ public:
static void
operator delete(void *ptr, size_t size) throw ();
- sp_head();
+ sp_head(stored_procedure_type type);
/// Initialize after we have reset mem_root
void
@@ -327,8 +339,8 @@ public:
bool
execute_trigger(THD *thd,
- const LEX_STRING *db_name,
- const LEX_STRING *table_name,
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name,
GRANT_INFO *grant_info);
bool
@@ -343,9 +355,162 @@ public:
bool
show_create_routine(THD *thd, int type);
+ MEM_ROOT *get_main_mem_root() { return &main_mem_root; }
+
int
add_instr(sp_instr *instr);
+ bool
+ add_instr_jump(THD *thd, sp_pcontext *spcont);
+
+ bool
+ add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest);
+
+ bool
+ add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont,
+ sp_label *lab);
+ bool
+ add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont)
+ {
+ return add_instr_jump_forward_with_backpatch(thd, spcont,
+ spcont->last_label());
+ }
+
+ Item *adjust_assignment_source(THD *thd, Item *val, Item *val2);
+ /**
+ @param thd - the current thd
+ @param spcont - the current parse context
+ @param spv - the SP variable
+ @param val - the value to be assigned to the variable
+ @param lex - the LEX that was used to create "val"
+ @param responsible_to_free_lex - if the generated sp_instr_set should
+ free "lex".
+ @retval true - on error
+ @retval false - on success
+ */
+ bool set_local_variable(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv, Item *val, LEX *lex,
+ bool responsible_to_free_lex);
+ bool set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv, uint field_idx,
+ Item *val, LEX *lex);
+ bool set_local_variable_row_field_by_name(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv,
+ const LEX_CSTRING *field_name,
+ Item *val, LEX *lex);
+private:
+ /**
+ Generate a code to set a single cursor parameter variable.
+ @param thd - current thd, for mem_root allocations.
+ @param param_spcont - the context of the parameter block
+ @param idx - the index of the parameter
+ @param prm - the actual parameter (contains information about
+ the assignment source expression Item,
+ its free list, and its LEX)
+ */
+ bool add_set_cursor_param_variable(THD *thd,
+ sp_pcontext *param_spcont, uint idx,
+ sp_assignment_lex *prm)
+ {
+ DBUG_ASSERT(idx < param_spcont->context_var_count());
+ sp_variable *spvar= param_spcont->get_context_variable(idx);
+ /*
+ add_instr() gets free_list from m_thd->free_list.
+ Initialize it before the set_local_variable() call.
+ */
+ DBUG_ASSERT(m_thd->free_list == NULL);
+ m_thd->free_list= prm->get_free_list();
+ if (set_local_variable(thd, param_spcont, spvar, prm->get_item(), prm, true))
+ return true;
+ /*
+ Safety:
+ The item and its free_list are now fully owned by the sp_instr_set
+ instance, created by set_local_variable(). The sp_instr_set instance
+ is now responsible for freeing the item and the free_list.
+ Reset the "item" and the "free_list" members of "prm",
+ to avoid double pointers to the same objects from "prm" and
+ from the sp_instr_set instance.
+ */
+ prm->set_item_and_free_list(NULL, NULL);
+ return false;
+ }
+
+ /**
+ Generate a code to set all cursor parameter variables.
+ This method is called only when parameters exists,
+ and the number of formal parameters matches the number of actual
+ parameters. See also comments to add_open_cursor().
+ */
+ bool add_set_cursor_param_variables(THD *thd, sp_pcontext *param_spcont,
+ List<sp_assignment_lex> *parameters)
+ {
+ DBUG_ASSERT(param_spcont->context_var_count() == parameters->elements);
+ sp_assignment_lex *prm;
+ List_iterator<sp_assignment_lex> li(*parameters);
+ for (uint idx= 0; (prm= li++); idx++)
+ {
+ if (add_set_cursor_param_variable(thd, param_spcont, idx, prm))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ Generate a code to set all cursor parameter variables for a FOR LOOP, e.g.:
+ FOR index IN cursor(1,2,3)
+ @param
+ */
+ bool add_set_for_loop_cursor_param_variables(THD *thd,
+ sp_pcontext *param_spcont,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters);
+
+public:
+ /**
+ Generate a code for an "OPEN cursor" statement.
+ @param thd - current thd, for mem_root allocations
+ @param spcont - the context of the cursor
+ @param offset - the offset of the cursor
+ @param param_spcont - the context of the cursor parameter block
+ @param parameters - the list of the OPEN actual parameters
+
+ The caller must make sure that the number of local variables
+ in "param_spcont" (formal parameters) matches the number of list elements
+ in "parameters" (actual parameters).
+ NULL in either of them means 0 parameters.
+ */
+ bool add_open_cursor(THD *thd, sp_pcontext *spcont,
+ uint offset,
+ sp_pcontext *param_spcont,
+ List<sp_assignment_lex> *parameters);
+
+ /**
+ Generate an initiation code for a CURSOR FOR LOOP, e.g.:
+ FOR index IN cursor -- cursor without parameters
+ FOR index IN cursor(1,2,3) -- cursor with parameters
+
+ The code generated by this method does the following during SP run-time:
+ - Sets all cursor parameter vartiables from "parameters"
+ - Initializes the index ROW-type variable from the cursor
+ (the structure is copied from the cursor to the index variable)
+ - The cursor gets opened
+ - The first records is fetched from the cursor to the variable "index".
+
+ @param thd - the current thread (for mem_root and error reporting)
+ @param spcont - the current parse context
+ @param index - the loop "index" ROW-type variable
+ @param pcursor - the cursor
+ @param coffset - the cursor offset
+ @param param_lex - the LEX that owns Items in "parameters"
+ @param parameters - the cursor parameters Item array
+ @retval true - on error (EOM)
+ @retval false - on success
+ */
+ bool add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont,
+ sp_variable *index,
+ const sp_pcursor *pcursor, uint coffset,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters);
/**
Returns true if any substatement in the routine directly
(not through another routine) modifies data/changes table.
@@ -367,6 +532,8 @@ public:
return i;
}
+ bool replace_instr_to_nop(THD *thd, uint ip);
+
/*
Resets lex in 'thd' and keeps a copy of the old one.
@@ -375,6 +542,23 @@ public:
bool
reset_lex(THD *thd);
+ bool
+ reset_lex(THD *thd, sp_lex_local *sublex);
+
+ /**
+ Merge two LEX instances.
+ @param oldlex - the upper level LEX we're going to restore to.
+ @param sublex - the local lex that have just parsed some substatement.
+ @returns - false on success, true on error (e.g. failed to
+ merge the routine list or the table list).
+ This method is shared by:
+ - restore_lex(), when the old LEX is popped by sp_head::m_lex.pop()
+ - THD::restore_from_local_lex_to_old_lex(), when the old LEX
+ is stored in the caller's local variable.
+ */
+ bool
+ merge_lex(THD *thd, LEX *oldlex, LEX *sublex);
+
/**
Restores lex in 'thd' from our copy, but keeps some status from the
one in 'thd', like ptr, tables, fields, etc.
@@ -382,16 +566,40 @@ public:
@todo Conflicting comment in sp_head.cc
*/
bool
- restore_lex(THD *thd);
+ restore_lex(THD *thd)
+ {
+ DBUG_ENTER("sp_head::restore_lex");
+ LEX *oldlex= (LEX *) m_lex.pop();
+ if (!oldlex)
+ DBUG_RETURN(false); // Nothing to restore
+ LEX *sublex= thd->lex;
+ if (thd->restore_from_local_lex_to_old_lex(oldlex))// This restores thd->lex
+ DBUG_RETURN(true);
+ if (!sublex->sp_lex_in_use)
+ {
+ sublex->sphead= NULL;
+ lex_end(sublex);
+ delete sublex;
+ }
+ DBUG_RETURN(false);
+ }
/// Put the instruction on the backpatch list, associated with the label.
int
push_backpatch(THD *thd, sp_instr *, sp_label *);
+ int
+ push_backpatch_goto(THD *thd, sp_pcontext *ctx, sp_label *lab);
/// Update all instruction with this label in the backpatch list to
/// the current position.
void
backpatch(sp_label *);
+ void
+ backpatch_goto(THD *thd, sp_label *, sp_label *);
+
+ /// Check for unresolved goto label
+ bool
+ check_unresolved_goto();
/// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr.
int
@@ -405,26 +613,87 @@ public:
void
do_cont_backpatch();
- char *name(uint *lenp = 0) const
- {
- if (lenp)
- *lenp= (uint) m_name.length;
- return m_name.str;
- }
+ /// Add cpush instructions for all cursors declared in the current frame
+ bool sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext);
+
+ const LEX_CSTRING *name() const
+ { return &m_name; }
char *create_string(THD *thd, ulong *lenp);
- Field *create_result_field(uint field_max_length, const char *field_name,
+ Field *create_result_field(uint field_max_length, const LEX_CSTRING *field_name,
TABLE *table);
- bool fill_field_definition(THD *thd, LEX *lex,
- Column_definition *field_def);
+ /**
+ Check and prepare an instance of Column_definition for field creation
+ (fill all necessary attributes), for variables, parameters and
+ function return values.
+
+ @param[in] thd Thread handle
+ @param[in] lex Yacc parsing context
+ @param[out] field_def An instance of create_field to be filled
+
+ @retval false on success
+ @retval true on error
+ */
+ bool fill_field_definition(THD *thd, Column_definition *field_def)
+ {
+ const Type_handler *h= field_def->type_handler();
+ return h->Column_definition_fix_attributes(field_def) ||
+ field_def->sp_prepare_create_field(thd, mem_root);
+ }
+ bool row_fill_field_definitions(THD *thd, Row_definition_list *row)
+ {
+ /*
+ Prepare all row fields. This will (among other things)
+ - convert VARCHAR lengths from character length to octet length
+ - calculate interval lengths for SET and ENUM
+ */
+ List_iterator<Spvar_definition> it(*row);
+ for (Spvar_definition *def= it++; def; def= it++)
+ {
+ if (fill_spvar_definition(thd, def))
+ return true;
+ }
+ return false;
+ }
+ /**
+ Check and prepare a Column_definition for a variable or a parameter.
+ */
+ bool fill_spvar_definition(THD *thd, Column_definition *def)
+ {
+ if (fill_field_definition(thd, def))
+ return true;
+ def->pack_flag|= FIELDFLAG_MAYBE_NULL;
+ return false;
+ }
+ bool fill_spvar_definition(THD *thd, Column_definition *def,
+ LEX_CSTRING *name)
+ {
+ def->field_name= *name;
+ return fill_spvar_definition(thd, def);
+ }
+ /**
+ Set a column type reference for a parameter definition
+ */
+ void fill_spvar_using_type_reference(sp_variable *spvar,
+ Qualified_column_ident *ref)
+ {
+ spvar->field_def.set_column_type_ref(ref);
+ spvar->field_def.field_name= spvar->name;
+ m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
+ }
+
+ void set_chistics(const st_sp_chistics &chistics);
void set_info(longlong created, longlong modified,
- st_sp_chistics *chistics, sql_mode_t sql_mode);
+ const st_sp_chistics &chistics, sql_mode_t sql_mode);
void set_definer(const char *definer, uint definerlen);
- void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
+ void set_definer(const LEX_CSTRING *user_name, const LEX_CSTRING *host_name)
+ {
+ m_definer.copy(mem_root, user_name, host_name);
+ }
void reset_thd_mem_root(THD *thd);
@@ -510,7 +779,7 @@ public:
DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x",
prelocking_ctx->get_stmt_unsafe_flags()));
DBUG_PRINT("info", ("sp_head(0x%p=%s)->unsafe_flags: 0x%x",
- this, name(), unsafe_flags));
+ this, name()->str, unsafe_flags));
prelocking_ctx->set_stmt_unsafe_flags(unsafe_flags);
DBUG_VOID_RETURN;
}
@@ -525,12 +794,17 @@ private:
sp_pcontext *m_pcont; ///< Parse context
List<LEX> m_lex; ///< Temp. store for the other lex
DYNAMIC_ARRAY m_instr; ///< The "instructions"
+
+ enum backpatch_instr_type { GOTO, CPOP, HPOP };
typedef struct
{
sp_label *lab;
sp_instr *instr;
+ backpatch_instr_type instr_type;
} bp_t;
List<bp_t> m_backpatch; ///< Instructions needing backpatching
+ List<bp_t> m_backpatch_goto; // Instructions needing backpatching (for goto)
+
/**
We need a special list for backpatching of instructions with a continue
destination (in the case of a continue handler catching an error in
@@ -568,9 +842,55 @@ private:
by routine.
*/
bool merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check);
+
+ /// Put the instruction on the a backpatch list, associated with the label.
+ int
+ push_backpatch(THD *thd, sp_instr *, sp_label *, List<bp_t> *list,
+ backpatch_instr_type itype);
+
}; // class sp_head : public Sql_alloc
+class sp_lex_cursor: public sp_lex_local, public Query_arena
+{
+ LEX_CSTRING m_cursor_name;
+public:
+ sp_lex_cursor(THD *thd, const LEX *oldlex, MEM_ROOT *mem_root_arg)
+ :sp_lex_local(thd, oldlex),
+ Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP),
+ m_cursor_name(null_clex_str)
+ { }
+ sp_lex_cursor(THD *thd, const LEX *oldlex)
+ :sp_lex_local(thd, oldlex),
+ Query_arena(thd->lex->sphead->get_main_mem_root(), STMT_INITIALIZED_FOR_SP)
+ { }
+ ~sp_lex_cursor() { free_items(); }
+ void cleanup_stmt() { }
+ Query_arena *query_arena() { return this; }
+ bool validate()
+ {
+ DBUG_ASSERT(sql_command == SQLCOM_SELECT);
+ if (result)
+ {
+ my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
+ return true;
+ }
+ return false;
+ }
+ bool stmt_finalize(THD *thd)
+ {
+ if (validate())
+ return true;
+ sp_lex_in_use= true;
+ free_list= thd->free_list;
+ thd->free_list= NULL;
+ return false;
+ }
+ const LEX_CSTRING *cursor_name() const { return &m_cursor_name; }
+ void set_cursor_name(const LEX_CSTRING *name) { m_cursor_name= *name; }
+};
+
+
//
// "Instructions"...
//
@@ -585,6 +905,7 @@ public:
uint marked;
uint m_ip; ///< My index
sp_pcontext *m_ctx; ///< My parse context
+ uint m_lineno;
/// Should give each a name or type code for debugging purposes?
sp_instr(uint ip, sp_pcontext *ctx)
@@ -728,6 +1049,9 @@ public:
int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
sp_instr* instr);
+ int cursor_reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
+ sp_instr *instr);
+
inline uint sql_command() const
{
return (uint)m_lex->sql_command;
@@ -737,6 +1061,11 @@ public:
{
m_lex->safe_to_cache_query= 0;
}
+
+ const LEX_CSTRING *cursor_name() const
+ {
+ return m_lex->cursor_name();
+ }
private:
LEX *m_lex;
@@ -810,9 +1139,9 @@ class sp_instr_set : public sp_instr
public:
sp_instr_set(uint ip, sp_pcontext *ctx,
- uint offset, Item *val, enum enum_field_types type_arg,
+ uint offset, Item *val,
LEX *lex, bool lex_resp)
- : sp_instr(ip, ctx), m_offset(offset), m_value(val), m_type(type_arg),
+ : sp_instr(ip, ctx), m_offset(offset), m_value(val),
m_lex_keeper(lex, lex_resp)
{}
@@ -825,16 +1154,87 @@ public:
virtual void print(String *str);
-private:
+protected:
uint m_offset; ///< Frame offset
Item *m_value;
- enum enum_field_types m_type; ///< The declared type
sp_lex_keeper m_lex_keeper;
}; // class sp_instr_set : public sp_instr
+/*
+ This class handles assignments of a ROW fields:
+ DECLARE rec ROW (a INT,b INT);
+ SET rec.a= 10;
+*/
+class sp_instr_set_row_field : public sp_instr_set
+{
+ sp_instr_set_row_field(const sp_instr_set_row_field &); // Prevent use of this
+ void operator=(sp_instr_set_row_field &);
+ uint m_field_offset;
+
+public:
+
+ sp_instr_set_row_field(uint ip, sp_pcontext *ctx,
+ uint offset, uint field_offset,
+ Item *val,
+ LEX *lex, bool lex_resp)
+ : sp_instr_set(ip, ctx, offset, val, lex, lex_resp),
+ m_field_offset(field_offset)
+ {}
+
+ virtual ~sp_instr_set_row_field()
+ {}
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+}; // class sp_instr_set_field : public sp_instr_set
+
+
+/**
+ This class handles assignment instructions like this:
+ DECLARE
+ CURSOR cur IS SELECT * FROM t1;
+ rec cur%ROWTYPE;
+ BEGIN
+ rec.column1:= 10; -- This instruction
+ END;
+
+ The idea is that during sp_rcontext::create() we do not know the extact
+ structure of "rec". It gets resolved at run time, during the corresponding
+ sp_instr_cursor_copy_struct::exec_core().
+
+ So sp_instr_set_row_field_by_name searches for ROW fields by name,
+ while sp_instr_set_row_field (see above) searches for ROW fields by index.
+*/
+class sp_instr_set_row_field_by_name : public sp_instr_set
+{
+ // Prevent use of this
+ sp_instr_set_row_field_by_name(const sp_instr_set_row_field &);
+ void operator=(sp_instr_set_row_field_by_name &);
+ const LEX_CSTRING m_field_name;
+
+public:
+
+ sp_instr_set_row_field_by_name(uint ip, sp_pcontext *ctx,
+ uint offset, const LEX_CSTRING &field_name,
+ Item *val,
+ LEX *lex, bool lex_resp)
+ : sp_instr_set(ip, ctx, offset, val, lex, lex_resp),
+ m_field_name(field_name)
+ {}
+
+ virtual ~sp_instr_set_row_field_by_name()
+ {}
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+}; // class sp_instr_set_field_by_name : public sp_instr_set
+
+
/**
Set NEW/OLD row field value instruction. Used in triggers.
*/
@@ -1006,6 +1406,41 @@ private:
}; // class sp_instr_jump_if_not : public sp_instr_jump
+class sp_instr_preturn : public sp_instr
+{
+ sp_instr_preturn(const sp_instr_preturn &); /**< Prevent use of these */
+ void operator=(sp_instr_preturn &);
+
+public:
+
+ sp_instr_preturn(uint ip, sp_pcontext *ctx)
+ : sp_instr(ip, ctx)
+ {}
+
+ virtual ~sp_instr_preturn()
+ {}
+
+ virtual int execute(THD *thd, uint *nextp)
+ {
+ DBUG_ENTER("sp_instr_preturn::execute");
+ *nextp= UINT_MAX;
+ DBUG_RETURN(0);
+ }
+
+ virtual void print(String *str)
+ {
+ str->append(STRING_WITH_LEN("preturn"));
+ }
+
+ virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads)
+ {
+ marked= 1;
+ return UINT_MAX;
+ }
+
+}; // class sp_instr_preturn : public sp_instr
+
+
class sp_instr_freturn : public sp_instr
{
sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */
@@ -1014,8 +1449,8 @@ class sp_instr_freturn : public sp_instr
public:
sp_instr_freturn(uint ip, sp_pcontext *ctx,
- Item *val, enum enum_field_types type_arg, LEX *lex)
- : sp_instr(ip, ctx), m_value(val), m_type(type_arg),
+ Item *val, const Type_handler *handler, LEX *lex)
+ : sp_instr(ip, ctx), m_value(val), m_type_handler(handler),
m_lex_keeper(lex, TRUE)
{}
@@ -1037,7 +1472,7 @@ public:
protected:
Item *m_value;
- enum enum_field_types m_type;
+ const Type_handler *m_type_handler;
sp_lex_keeper m_lex_keeper;
}; // class sp_instr_freturn : public sp_instr
@@ -1124,6 +1559,11 @@ public:
virtual ~sp_instr_hpop()
{}
+ void update_count(uint count)
+ {
+ m_count= count;
+ }
+
virtual int execute(THD *thd, uint *nextp);
virtual void print(String *str);
@@ -1216,6 +1656,11 @@ public:
virtual ~sp_instr_cpop()
{}
+ void update_count(uint count)
+ {
+ m_count= count;
+ }
+
virtual int execute(THD *thd, uint *nextp);
virtual void print(String *str);
@@ -1254,6 +1699,30 @@ private:
}; // class sp_instr_copen : public sp_instr_stmt
+/**
+ Initialize the structure of a cursor%ROWTYPE variable
+ from the LEX containing the cursor SELECT statement.
+*/
+class sp_instr_cursor_copy_struct: public sp_instr
+{
+ /**< Prevent use of these */
+ sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &);
+ void operator=(sp_instr_cursor_copy_struct &);
+ sp_lex_keeper m_lex_keeper;
+ uint m_var;
+public:
+ sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx,
+ sp_lex_cursor *lex, uint voffs)
+ : sp_instr(ip, ctx), m_lex_keeper(lex, FALSE), m_var(voffs)
+ {}
+ virtual ~sp_instr_cursor_copy_struct()
+ {}
+ virtual int execute(THD *thd, uint *nextp);
+ virtual int exec_core(THD *thd, uint *nextp);
+ virtual void print(String *str);
+};
+
+
class sp_instr_cclose : public sp_instr
{
sp_instr_cclose(const sp_instr_cclose &); /**< Prevent use of these */
@@ -1401,10 +1870,11 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
enum_mdl_type mdl_type);
Item *
-sp_prepare_func_item(THD* thd, Item **it_addr);
+sp_prepare_func_item(THD* thd, Item **it_addr, uint cols= 1);
bool
-sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr);
+sp_eval_expr(THD *thd, Item *result_item, Field *result_field,
+ Item **expr_item_ptr);
/**
@} (end of group Stored_Routines)
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 9a6353c9337..d98f8005945 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -27,19 +27,50 @@ bool sp_condition_value::equals(const sp_condition_value *cv) const
{
DBUG_ASSERT(cv);
+ /*
+ The following test disallows duplicate handlers,
+ including user defined exceptions with the same WHEN clause:
+ DECLARE
+ a EXCEPTION;
+ b EXCEPTION;
+ BEGIN
+ RAUSE a;
+ EXCEPTION
+ WHEN a THEN RETURN 'a0';
+ WHEN a THEN RETURN 'a1';
+ END
+ */
if (this == cv)
return true;
- if (type != cv->type)
+ /*
+ The test below considers two conditions of the same type as equal
+ (except for the user defined exceptions) to avoid declaring duplicate
+ handlers.
+
+ All user defined conditions have type==SQLSTATE
+ with the same SQL state and error code.
+ It's OK to have multiple user defined conditions:
+ DECLARE
+ a EXCEPTION;
+ b EXCEPTION;
+ BEGIN
+ RAISE a;
+ EXCEPTION
+ WHEN a THEN RETURN 'a';
+ WHEN b THEN RETURN 'b';
+ END;
+ */
+ if (type != cv->type || m_is_user_defined || cv->m_is_user_defined)
return false;
switch (type)
{
case sp_condition_value::ERROR_CODE:
- return (mysqlerr == cv->mysqlerr);
+ return (get_sql_errno() == cv->get_sql_errno());
case sp_condition_value::SQLSTATE:
- return (strcmp(sql_state, cv->sql_state) == 0);
+ return Sql_state::eq(cv);
default:
return true;
@@ -56,6 +87,7 @@ void sp_pcontext::init(uint var_offset,
m_num_case_exprs= num_case_expressions;
m_labels.empty();
+ m_goto_labels.empty();
}
@@ -98,6 +130,12 @@ sp_pcontext *sp_pcontext::push_context(THD *thd, sp_pcontext::enum_scope scope)
}
+bool cmp_labels(sp_label *a, sp_label *b)
+{
+ return (my_strcasecmp(system_charset_info, a->name.str, b->name.str) == 0
+ && a->type == b->type);
+}
+
sp_pcontext *sp_pcontext::pop_context()
{
m_parent->m_max_var_index+= m_max_var_index;
@@ -109,6 +147,18 @@ sp_pcontext *sp_pcontext::pop_context()
if (m_num_case_exprs > m_parent->m_num_case_exprs)
m_parent->m_num_case_exprs= m_num_case_exprs;
+ /*
+ ** Push unresolved goto label to parent context
+ */
+ sp_label *label;
+ List_iterator_fast<sp_label> li(m_goto_labels);
+ while ((label= li++))
+ {
+ if (label->ip == 0)
+ {
+ m_parent->m_goto_labels.add_unique(label, &cmp_labels);
+ }
+ }
return m_parent;
}
@@ -149,7 +199,7 @@ uint sp_pcontext::diff_cursors(const sp_pcontext *ctx, bool exclusive) const
}
-sp_variable *sp_pcontext::find_variable(LEX_STRING name,
+sp_variable *sp_pcontext::find_variable(const LEX_CSTRING *name,
bool current_scope_only) const
{
uint i= m_vars.elements() - m_pboundary;
@@ -159,7 +209,7 @@ sp_variable *sp_pcontext::find_variable(LEX_STRING name,
sp_variable *p= m_vars.at(i);
if (my_strnncoll(system_charset_info,
- (const uchar *)name.str, name.length,
+ (const uchar *)name->str, name->length,
(const uchar *)p->name.str, p->name.length) == 0)
{
return p;
@@ -172,10 +222,46 @@ sp_variable *sp_pcontext::find_variable(LEX_STRING name,
}
+/*
+ Find a variable by its run-time offset.
+ If the variable with a desired run-time offset is not found in this
+ context frame, it's recursively searched on parent context frames.
+
+ Note, context frames can have holes:
+ CREATE PROCEDURE p1() AS
+ x0 INT:=100;
+ CURSOR cur(p0 INT, p1 INT) IS SELECT p0, p1;
+ x1 INT:=101;
+ BEGIN
+ ...
+ END;
+ The variables (x0 and x1) and the cursor parameters (p0 and p1)
+ reside in separate parse context frames.
+
+ The variables reside on the top level parse context frame:
+ - x0 has frame offset 0 and run-time offset 0
+ - x1 has frame offset 1 and run-time offset 3
+
+ The cursor parameters reside on the second level parse context frame:
+ - p0 has frame offset 0 and run-time offset 1
+ - p1 has frame offset 1 and run-time offset 2
+
+ Run-time offsets on a frame can have holes, but offsets monotonocally grow,
+ so run-time offsets of all variables are not greater than the run-time offset
+ of the very last variable in this frame.
+*/
sp_variable *sp_pcontext::find_variable(uint offset) const
{
- if (m_var_offset <= offset && offset < m_var_offset + m_vars.elements())
- return m_vars.at(offset - m_var_offset); // This frame
+ if (m_var_offset <= offset &&
+ m_vars.elements() &&
+ offset <= get_last_context_variable()->offset)
+ {
+ for (uint i= 0; i < m_vars.elements(); i++)
+ {
+ if (m_vars.at(i)->offset == offset)
+ return m_vars.at(i); // This frame
+ }
+ }
return m_parent ?
m_parent->find_variable(offset) : // Some previous frame
@@ -183,10 +269,10 @@ sp_variable *sp_pcontext::find_variable(uint offset) const
}
-sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name)
+sp_variable *sp_pcontext::add_variable(THD *thd, const LEX_CSTRING *name)
{
sp_variable *p=
- new (thd->mem_root) sp_variable(name, current_var_count());
+ new (thd->mem_root) sp_variable(name, m_var_offset + m_max_var_index);
if (!p)
return NULL;
@@ -196,29 +282,66 @@ sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name)
return m_vars.append(p) ? NULL : p;
}
-
-sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip)
+sp_label *sp_pcontext::push_label(THD *thd, const LEX_CSTRING *name, uint ip,
+ sp_label::enum_type type,
+ List<sp_label> *list)
{
sp_label *label=
- new (thd->mem_root) sp_label(name, ip, sp_label::IMPLICIT, this);
+ new (thd->mem_root) sp_label(name, ip, type, this);
if (!label)
return NULL;
- m_labels.push_front(label, thd->mem_root);
+ list->push_front(label, thd->mem_root);
return label;
}
+sp_label *sp_pcontext::find_goto_label(const LEX_CSTRING *name, bool recusive)
+{
+ List_iterator_fast<sp_label> li(m_goto_labels);
+ sp_label *lab;
+
+ while ((lab= li++))
+ {
+ if (my_strcasecmp(system_charset_info, name->str, lab->name.str) == 0)
+ return lab;
+ }
-sp_label *sp_pcontext::find_label(LEX_STRING name)
+ if (!recusive)
+ return NULL;
+
+ /*
+ Note about exception handlers.
+ See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
+ section 13.1 <compound statement>,
+ syntax rule 4.
+ In short, a DECLARE HANDLER block can not refer
+ to labels from the parent context, as they are out of scope.
+ */
+ if (m_scope == HANDLER_SCOPE && m_parent)
+ {
+ if (m_parent->m_parent)
+ {
+ // Skip the parent context
+ return m_parent->m_parent->find_goto_label(name);
+ }
+ }
+
+ return m_parent && (m_scope == REGULAR_SCOPE) ?
+ m_parent->find_goto_label(name) :
+ NULL;
+}
+
+
+sp_label *sp_pcontext::find_label(const LEX_CSTRING *name)
{
List_iterator_fast<sp_label> li(m_labels);
sp_label *lab;
while ((lab= li++))
{
- if (my_strcasecmp(system_charset_info, name.str, lab->name.str) == 0)
+ if (my_strcasecmp(system_charset_info, name->str, lab->name.str) == 0)
return lab;
}
@@ -236,8 +359,25 @@ sp_label *sp_pcontext::find_label(LEX_STRING name)
}
+sp_label *sp_pcontext::find_label_current_loop_start()
+{
+ List_iterator_fast<sp_label> li(m_labels);
+ sp_label *lab;
+
+ while ((lab= li++))
+ {
+ if (lab->type == sp_label::ITERATION)
+ return lab;
+ }
+ // See a comment in sp_pcontext::find_label()
+ return (m_parent && (m_scope == REGULAR_SCOPE)) ?
+ m_parent->find_label_current_loop_start() :
+ NULL;
+}
+
+
bool sp_pcontext::add_condition(THD *thd,
- LEX_STRING name,
+ const LEX_CSTRING *name,
sp_condition_value *value)
{
sp_condition *p= new (thd->mem_root) sp_condition(name, value);
@@ -249,7 +389,7 @@ bool sp_pcontext::add_condition(THD *thd,
}
-sp_condition_value *sp_pcontext::find_condition(LEX_STRING name,
+sp_condition_value *sp_pcontext::find_condition(const LEX_CSTRING *name,
bool current_scope_only) const
{
uint i= m_conditions.elements();
@@ -258,9 +398,7 @@ sp_condition_value *sp_pcontext::find_condition(LEX_STRING name,
{
sp_condition *p= m_conditions.at(i);
- if (my_strnncoll(system_charset_info,
- (const uchar *) name.str, name.length,
- (const uchar *) p->name.str, p->name.length) == 0)
+ if (p->eq_name(name))
{
return p->value;
}
@@ -272,6 +410,38 @@ sp_condition_value *sp_pcontext::find_condition(LEX_STRING name,
}
+static sp_condition_value
+ // Warnings
+ cond_no_data_found(ER_SP_FETCH_NO_DATA, "01000"),
+ // Errors
+ cond_invalid_cursor(ER_SP_CURSOR_NOT_OPEN, "24000"),
+ cond_dup_val_on_index(ER_DUP_ENTRY, "23000"),
+ cond_too_many_rows(ER_TOO_MANY_ROWS, "42000");
+
+
+static sp_condition sp_predefined_conditions[]=
+{
+ // Warnings
+ sp_condition(C_STRING_WITH_LEN("NO_DATA_FOUND"), &cond_no_data_found),
+ // Errors
+ sp_condition(C_STRING_WITH_LEN("INVALID_CURSOR"), &cond_invalid_cursor),
+ sp_condition(C_STRING_WITH_LEN("DUP_VAL_ON_INDEX"), &cond_dup_val_on_index),
+ sp_condition(C_STRING_WITH_LEN("TOO_MANY_ROWS"), &cond_too_many_rows)
+};
+
+
+sp_condition_value *
+sp_pcontext::find_predefined_condition(const LEX_CSTRING *name) const
+{
+ for (uint i= 0; i < array_elements(sp_predefined_conditions) ; i++)
+ {
+ if (sp_predefined_conditions[i].eq_name(name))
+ return sp_predefined_conditions[i].value;
+ }
+ return NULL;
+}
+
+
sp_handler *sp_pcontext::add_handler(THD *thd,
sp_handler::enum_type type)
{
@@ -305,10 +475,57 @@ bool sp_pcontext::check_duplicate_handler(
}
+bool sp_condition_value::matches(const Sql_condition_identity &value,
+ const sp_condition_value *found_cv) const
+{
+ bool user_value_matched= !value.get_user_condition_value() ||
+ this == value.get_user_condition_value();
+
+ switch (type)
+ {
+ case sp_condition_value::ERROR_CODE:
+ return user_value_matched &&
+ value.get_sql_errno() == get_sql_errno() &&
+ (!found_cv || found_cv->type > sp_condition_value::ERROR_CODE);
+
+ case sp_condition_value::SQLSTATE:
+ return user_value_matched &&
+ Sql_state::eq(&value) &&
+ (!found_cv || found_cv->type > sp_condition_value::SQLSTATE);
+
+ case sp_condition_value::WARNING:
+ return user_value_matched &&
+ (value.Sql_state::is_warning() ||
+ value.get_level() == Sql_condition::WARN_LEVEL_WARN) &&
+ !found_cv;
+
+ case sp_condition_value::NOT_FOUND:
+ return user_value_matched &&
+ value.Sql_state::is_not_found() &&
+ !found_cv;
+
+ case sp_condition_value::EXCEPTION:
+ /*
+ In sql_mode=ORACLE this construct should catch both errors and warnings:
+ EXCEPTION
+ WHEN OTHERS THEN ...;
+ E.g. NO_DATA_FOUND is more like a warning than an error,
+ and it should be caught.
+
+ We don't check user_value_matched here.
+ "WHEN OTHERS" catches all user defined exception.
+ */
+ return (((current_thd->variables.sql_mode & MODE_ORACLE) ||
+ (value.Sql_state::is_exception() &&
+ value.get_level() == Sql_condition::WARN_LEVEL_ERROR)) &&
+ !found_cv);
+ }
+ return false;
+}
+
+
sp_handler*
-sp_pcontext::find_handler(const char *sql_state,
- uint sql_errno,
- Sql_condition::enum_warning_level level) const
+sp_pcontext::find_handler(const Sql_condition_identity &value) const
{
sp_handler *found_handler= NULL;
sp_condition_value *found_cv= NULL;
@@ -322,53 +539,10 @@ sp_pcontext::find_handler(const char *sql_state,
while ((cv= li++))
{
- switch (cv->type)
+ if (cv->matches(value, found_cv))
{
- case sp_condition_value::ERROR_CODE:
- if (sql_errno == cv->mysqlerr &&
- (!found_cv ||
- found_cv->type > sp_condition_value::ERROR_CODE))
- {
- found_cv= cv;
- found_handler= h;
- }
- break;
-
- case sp_condition_value::SQLSTATE:
- if (strcmp(sql_state, cv->sql_state) == 0 &&
- (!found_cv ||
- found_cv->type > sp_condition_value::SQLSTATE))
- {
- found_cv= cv;
- found_handler= h;
- }
- break;
-
- case sp_condition_value::WARNING:
- if ((is_sqlstate_warning(sql_state) ||
- level == Sql_condition::WARN_LEVEL_WARN) && !found_cv)
- {
- found_cv= cv;
- found_handler= h;
- }
- break;
-
- case sp_condition_value::NOT_FOUND:
- if (is_sqlstate_not_found(sql_state) && !found_cv)
- {
- found_cv= cv;
- found_handler= h;
- }
- break;
-
- case sp_condition_value::EXCEPTION:
- if (is_sqlstate_exception(sql_state) &&
- level == Sql_condition::WARN_LEVEL_ERROR && !found_cv)
- {
- found_cv= cv;
- found_handler= h;
- }
- break;
+ found_cv= cv;
+ found_handler= h;
}
}
}
@@ -411,64 +585,98 @@ sp_pcontext::find_handler(const char *sql_state,
if (!p || !p->m_parent)
return NULL;
- return p->m_parent->find_handler(sql_state, sql_errno, level);
+ return p->m_parent->find_handler(value);
}
-bool sp_pcontext::add_cursor(LEX_STRING name)
+bool sp_pcontext::add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx,
+ sp_lex_cursor *lex)
{
if (m_cursors.elements() == m_max_cursor_index)
++m_max_cursor_index;
- return m_cursors.append(name);
+ return m_cursors.append(sp_pcursor(name, param_ctx, lex));
}
-bool sp_pcontext::find_cursor(LEX_STRING name,
- uint *poff,
- bool current_scope_only) const
+const sp_pcursor *sp_pcontext::find_cursor(const LEX_CSTRING *name,
+ uint *poff,
+ bool current_scope_only) const
{
uint i= m_cursors.elements();
while (i--)
{
- LEX_STRING n= m_cursors.at(i);
+ LEX_CSTRING n= m_cursors.at(i);
if (my_strnncoll(system_charset_info,
- (const uchar *) name.str, name.length,
+ (const uchar *) name->str, name->length,
(const uchar *) n.str, n.length) == 0)
{
*poff= m_cursor_offset + i;
- return true;
+ return &m_cursors.at(i);
}
}
return (!current_scope_only && m_parent) ?
m_parent->find_cursor(name, poff, false) :
- false;
+ NULL;
}
void sp_pcontext::retrieve_field_definitions(
- List<Column_definition> *field_def_lst) const
+ List<Spvar_definition> *field_def_lst) const
{
/* Put local/context fields in the result list. */
+ size_t next_child= 0;
for (size_t i= 0; i < m_vars.elements(); ++i)
{
sp_variable *var_def= m_vars.at(i);
+ /*
+ The context can have holes in run-time offsets,
+ the missing offsets reside on the children contexts in such cases.
+ Example:
+ CREATE PROCEDURE p1() AS
+ x0 INT:=100; -- context 0, position 0, run-time 0
+ CURSOR cur(
+ p0 INT, -- context 1, position 0, run-time 1
+ p1 INT -- context 1, position 1, run-time 2
+ ) IS SELECT p0, p1;
+ x1 INT:=101; -- context 0, position 1, run-time 3
+ BEGIN
+ ...
+ END;
+ See more comments in sp_pcontext::find_variable().
+ We must retrieve the definitions in the order of their run-time offsets.
+ Check that there are children that should go before the current variable.
+ */
+ for ( ; next_child < m_children.elements(); next_child++)
+ {
+ sp_pcontext *child= m_children.at(next_child);
+ if (!child->context_var_count() ||
+ child->get_context_variable(0)->offset > var_def->offset)
+ break;
+ /*
+ All variables on the embedded context (that fills holes of the parent)
+ should have the run-time offset strictly less than var_def.
+ */
+ DBUG_ASSERT(child->get_context_variable(0)->offset < var_def->offset);
+ DBUG_ASSERT(child->get_last_context_variable()->offset < var_def->offset);
+ child->retrieve_field_definitions(field_def_lst);
+ }
field_def_lst->push_back(&var_def->field_def);
}
- /* Put the fields of the enclosed contexts in the result list. */
+ /* Put the fields of the remaining enclosed contexts in the result list. */
- for (size_t i= 0; i < m_children.elements(); ++i)
+ for (size_t i= next_child; i < m_children.elements(); ++i)
m_children.at(i)->retrieve_field_definitions(field_def_lst);
}
-const LEX_STRING *sp_pcontext::find_cursor(uint offset) const
+const sp_pcursor *sp_pcontext::find_cursor(uint offset) const
{
if (m_cursor_offset <= offset &&
offset < m_cursor_offset + m_cursors.elements())
@@ -480,3 +688,35 @@ const LEX_STRING *sp_pcontext::find_cursor(uint offset) const
m_parent->find_cursor(offset) : // Some previous frame
NULL; // Index out of bounds
}
+
+
+bool sp_pcursor::check_param_count_with_error(uint param_count) const
+{
+ if (param_count != (m_param_context ?
+ m_param_context->context_var_count() : 0))
+ {
+ my_error(ER_WRONG_PARAMCOUNT_TO_CURSOR, MYF(0), LEX_CSTRING::str);
+ return true;
+ }
+ return false;
+}
+
+
+const Spvar_definition *
+sp_variable::find_row_field(const LEX_CSTRING *var_name,
+ const LEX_CSTRING *field_name,
+ uint *row_field_offset)
+{
+ if (!field_def.is_row())
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "'%s' is not a row variable", MYF(0), var_name->str);
+ return NULL;
+ }
+ const Spvar_definition *def;
+ if ((def= field_def.find_row_field_by_name(field_name, row_field_offset)))
+ return def;
+ my_error(ER_ROW_VARIABLE_DOES_NOT_HAVE_FIELD, MYF(0),
+ var_name->str, field_name->str);
+ return NULL;
+}
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 2a080536b8a..215ebbe5f77 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -41,7 +41,7 @@ public:
};
/// Name of the SP-variable.
- LEX_STRING name;
+ LEX_CSTRING name;
/// Mode of the SP-variable.
enum_mode mode;
@@ -57,18 +57,35 @@ public:
Item *default_value;
/// Full type information (field meta-data) of the SP-variable.
- Column_definition field_def;
+ Spvar_definition field_def;
/// Field-type of the SP-variable.
- enum_field_types sql_type() const { return field_def.sql_type; }
+ enum_field_types sql_type() const { return field_def.real_field_type(); }
+
+ const Type_handler *type_handler() const { return field_def.type_handler(); }
+
public:
- sp_variable(LEX_STRING _name, uint _offset)
+ sp_variable(const LEX_CSTRING *name_arg, uint offset_arg)
:Sql_alloc(),
- name(_name),
+ name(*name_arg),
mode(MODE_IN),
- offset(_offset),
+ offset(offset_arg),
default_value(NULL)
{ }
+ /*
+ Find a ROW field by its qualified name.
+ @param var_name - the name of the variable
+ @param field_name - the name of the variable field
+ @param[OUT] row_field_offset - the index of the field
+
+ @retval NULL if the variable with the given name was not found,
+ or it is not a row variable, or it does not have a field
+ with the given name, or a non-null pointer otherwise.
+ row_field_offset[0] is set only when the method returns !NULL.
+ */
+ const Spvar_definition *find_row_field(const LEX_CSTRING *var_name,
+ const LEX_CSTRING *field_name,
+ uint *row_field_offset);
};
///////////////////////////////////////////////////////////////////////////
@@ -80,6 +97,7 @@ public:
/// IF/WHILE/REPEAT/LOOP, when such statement is rewritten into a
/// combination of low-level jump/jump_if instructions and labels.
+
class sp_label : public Sql_alloc
{
public:
@@ -92,11 +110,14 @@ public:
BEGIN,
/// Label at iteration control
- ITERATION
+ ITERATION,
+
+ /// Label for jump
+ GOTO
};
/// Name of the label.
- LEX_STRING name;
+ LEX_CSTRING name;
/// Instruction pointer of the label.
uint ip;
@@ -108,15 +129,17 @@ public:
class sp_pcontext *ctx;
public:
- sp_label(LEX_STRING _name, uint _ip, enum_type _type, sp_pcontext *_ctx)
+ sp_label(const LEX_CSTRING *_name,
+ uint _ip, enum_type _type, sp_pcontext *_ctx)
:Sql_alloc(),
- name(_name),
+ name(*_name),
ip(_ip),
type(_type),
ctx(_ctx)
{ }
};
+
///////////////////////////////////////////////////////////////////////////
/// This class represents condition-value term in DECLARE CONDITION or
@@ -126,8 +149,9 @@ public:
/// In some sense, this class is a union -- a set of filled attributes
/// depends on the sp_condition_value::type value.
-class sp_condition_value : public Sql_alloc
+class sp_condition_value : public Sql_alloc, public Sql_state_errno
{
+ bool m_is_user_defined;
public:
enum enum_type
{
@@ -141,29 +165,31 @@ public:
/// Type of the condition value.
enum_type type;
- /// SQLSTATE of the condition value.
- char sql_state[SQLSTATE_LENGTH+1];
-
- /// MySQL error code of the condition value.
- uint mysqlerr;
-
public:
sp_condition_value(uint _mysqlerr)
:Sql_alloc(),
- type(ERROR_CODE),
- mysqlerr(_mysqlerr)
+ Sql_state_errno(_mysqlerr),
+ m_is_user_defined(false),
+ type(ERROR_CODE)
{ }
- sp_condition_value(const char *_sql_state)
+ sp_condition_value(uint _mysqlerr, const char *_sql_state)
:Sql_alloc(),
+ Sql_state_errno(_mysqlerr, _sql_state),
+ m_is_user_defined(false),
+ type(ERROR_CODE)
+ { }
+
+ sp_condition_value(const char *_sql_state, bool is_user_defined= false)
+ :Sql_alloc(),
+ Sql_state_errno(0, _sql_state),
+ m_is_user_defined(is_user_defined),
type(SQLSTATE)
- {
- memcpy(sql_state, _sql_state, SQLSTATE_LENGTH);
- sql_state[SQLSTATE_LENGTH]= 0;
- }
+ { }
sp_condition_value(enum_type _type)
:Sql_alloc(),
+ m_is_user_defined(false),
type(_type)
{
DBUG_ASSERT(type != ERROR_CODE && type != SQLSTATE);
@@ -175,8 +201,39 @@ public:
///
/// @return true if the instances are equal, false otherwise.
bool equals(const sp_condition_value *cv) const;
+
+
+ /**
+ Checks if this condition is OK for search.
+ See also sp_context::find_handler().
+
+ @param identity - The condition identity
+ @param found_cv - A previously found matching condition or NULL.
+ @return true - If the current value matches identity and
+ makes a stronger match than the previously
+ found condition found_cv.
+ @return false - If the current value does not match identity,
+ of the current value makes a weaker match than found_cv.
+ */
+ bool matches(const Sql_condition_identity &identity,
+ const sp_condition_value *found_cv) const;
+
+ Sql_user_condition_identity get_user_condition_identity() const
+ {
+ return Sql_user_condition_identity(m_is_user_defined ? this : NULL);
+ }
};
+
+class sp_condition_value_user_defined: public sp_condition_value
+{
+public:
+ sp_condition_value_user_defined()
+ :sp_condition_value("45000", true)
+ { }
+};
+
+
///////////////////////////////////////////////////////////////////////////
/// This class represents 'DECLARE CONDITION' statement.
@@ -186,19 +243,66 @@ class sp_condition : public Sql_alloc
{
public:
/// Name of the condition.
- LEX_STRING name;
+ LEX_CSTRING name;
/// Value of the condition.
sp_condition_value *value;
public:
- sp_condition(LEX_STRING _name, sp_condition_value *_value)
+ sp_condition(const LEX_CSTRING *name_arg, sp_condition_value *value_arg)
:Sql_alloc(),
- name(_name),
- value(_value)
+ name(*name_arg),
+ value(value_arg)
{ }
+ sp_condition(const char *name_arg, size_t name_length_arg,
+ sp_condition_value *value_arg)
+ :value(value_arg)
+ {
+ name.str= name_arg;
+ name.length= name_length_arg;
+ }
+ bool eq_name(const LEX_CSTRING *str) const
+ {
+ return my_strnncoll(system_charset_info,
+ (const uchar *) name.str, name.length,
+ (const uchar *) str->str, str->length) == 0;
+ }
};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ class sp_pcursor.
+ Stores information about a cursor:
+ - Cursor's name in LEX_STRING.
+ - Cursor's formal parameter descriptions.
+
+ Formal parameter descriptions reside in a separate context block,
+ pointed by the "m_param_context" member.
+
+ m_param_context can be NULL. This means a cursor with no parameters.
+ Otherwise, the number of variables in m_param_context means
+ the number of cursor's formal parameters.
+
+ Note, m_param_context can be not NULL, but have no variables.
+ This is also means a cursor with no parameters (similar to NULL).
+*/
+class sp_pcursor: public LEX_CSTRING
+{
+ class sp_pcontext *m_param_context; // Formal parameters
+ class sp_lex_cursor *m_lex; // The cursor statement LEX
+public:
+ sp_pcursor(const LEX_CSTRING *name, class sp_pcontext *param_ctx,
+ class sp_lex_cursor *lex)
+ :LEX_CSTRING(*name), m_param_context(param_ctx), m_lex(lex)
+ { }
+ class sp_pcontext *param_context() const { return m_param_context; }
+ class sp_lex_cursor *lex() const { return m_lex; }
+ bool check_param_count_with_error(uint param_count) const;
+};
+
+
///////////////////////////////////////////////////////////////////////////
/// This class represents 'DECLARE HANDLER' statement.
@@ -267,6 +371,12 @@ public:
HANDLER_SCOPE
};
+ class Lex_for_loop: public Lex_for_loop_st
+ {
+ public:
+ Lex_for_loop() { init(); }
+ };
+
public:
sp_pcontext();
~sp_pcontext();
@@ -329,9 +439,22 @@ public:
uint context_var_count() const
{ return m_vars.elements(); }
- /// @return map index in this parsing context to runtime offset.
- uint var_context2runtime(uint i) const
- { return m_var_offset + i; }
+ /// return the i-th variable on the current context
+ sp_variable *get_context_variable(uint i) const
+ {
+ DBUG_ASSERT(i < m_vars.elements());
+ return m_vars.at(i);
+ }
+
+ /*
+ Return the i-th last context variable.
+ If i is 0, then return the very last variable in m_vars.
+ */
+ sp_variable *get_last_context_variable(uint i= 0) const
+ {
+ DBUG_ASSERT(i < m_vars.elements());
+ return m_vars.at(m_vars.elements() - i - 1);
+ }
/// Add SP-variable to the parsing context.
///
@@ -339,13 +462,13 @@ public:
/// @param name Name of the SP-variable.
///
/// @return instance of newly added SP-variable.
- sp_variable *add_variable(THD *thd, LEX_STRING name);
+ sp_variable *add_variable(THD *thd, const LEX_CSTRING *name);
/// Retrieve full type information about SP-variables in this parsing
/// context and its children.
///
/// @param field_def_lst[out] Container to store type information.
- void retrieve_field_definitions(List<Column_definition> *field_def_lst) const;
+ void retrieve_field_definitions(List<Spvar_definition> *field_def_lst) const;
/// Find SP-variable by name.
///
@@ -358,7 +481,7 @@ public:
/// @param current_scope_only A flag if we search only in current scope.
///
/// @return instance of found SP-variable, or NULL if not found.
- sp_variable *find_variable(LEX_STRING name, bool current_scope_only) const;
+ sp_variable *find_variable(const LEX_CSTRING *name, bool current_scope_only) const;
/// Find SP-variable by the offset in the root parsing context.
///
@@ -401,9 +524,31 @@ public:
// Labels.
/////////////////////////////////////////////////////////////////////////
- sp_label *push_label(THD *thd, LEX_STRING name, uint ip);
+ sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip,
+ sp_label::enum_type type, List<sp_label> * list);
+
+ sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip,
+ sp_label::enum_type type)
+ { return push_label(thd, name, ip, type, &m_labels); }
- sp_label *find_label(LEX_STRING name);
+ sp_label *push_goto_label(THD *thd, const LEX_CSTRING *name, uint ip,
+ sp_label::enum_type type)
+ { return push_label(thd, name, ip, type, &m_goto_labels); }
+
+ sp_label *push_label(THD *thd, const LEX_CSTRING *name, uint ip)
+ { return push_label(thd, name, ip, sp_label::IMPLICIT); }
+
+ sp_label *push_goto_label(THD *thd, const LEX_CSTRING *name, uint ip)
+ { return push_goto_label(thd, name, ip, sp_label::GOTO); }
+
+ sp_label *find_label(const LEX_CSTRING *name);
+
+ sp_label *find_goto_label(const LEX_CSTRING *name, bool recusive);
+
+ sp_label *find_goto_label(const LEX_CSTRING *name)
+ { return find_goto_label(name, true); }
+
+ sp_label *find_label_current_loop_start();
sp_label *last_label()
{
@@ -415,19 +560,56 @@ public:
return label;
}
+ sp_label *last_goto_label()
+ {
+ return m_goto_labels.head();
+ }
+
sp_label *pop_label()
{ return m_labels.pop(); }
+ bool block_label_declare(LEX_CSTRING *label)
+ {
+ sp_label *lab= find_label(label);
+ if (lab)
+ {
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), label->str);
+ return true;
+ }
+ return false;
+ }
+
/////////////////////////////////////////////////////////////////////////
// Conditions.
/////////////////////////////////////////////////////////////////////////
- bool add_condition(THD *thd, LEX_STRING name, sp_condition_value *value);
+ bool add_condition(THD *thd, const LEX_CSTRING *name,
+ sp_condition_value *value);
/// See comment for find_variable() above.
- sp_condition_value *find_condition(LEX_STRING name,
+ sp_condition_value *find_condition(const LEX_CSTRING *name,
bool current_scope_only) const;
+ sp_condition_value *
+ find_declared_or_predefined_condition(const LEX_CSTRING *name) const
+ {
+ sp_condition_value *p= find_condition(name, false);
+ if (p)
+ return p;
+ return find_predefined_condition(name);
+ }
+
+ bool declare_condition(THD *thd, const LEX_CSTRING *name,
+ sp_condition_value *val)
+ {
+ if (find_condition(name, true))
+ {
+ my_error(ER_SP_DUP_COND, MYF(0), name->str);
+ return true;
+ }
+ return add_condition(thd, name, val);
+ }
+
/////////////////////////////////////////////////////////////////////////
// Handlers.
/////////////////////////////////////////////////////////////////////////
@@ -454,26 +636,46 @@ public:
/// Find an SQL handler for the given SQL condition according to the
/// SQL-handler resolution rules. This function is used at runtime.
///
- /// @param sql_state The SQL condition state
- /// @param sql_errno The error code
+ /// @param value The error code and the SQL state
/// @param level The SQL condition level
///
/// @return a pointer to the found SQL-handler or NULL.
- sp_handler *find_handler(const char *sql_state,
- uint sql_errno,
- Sql_condition::enum_warning_level level) const;
+ sp_handler *find_handler(const Sql_condition_identity &identity) const;
/////////////////////////////////////////////////////////////////////////
// Cursors.
/////////////////////////////////////////////////////////////////////////
- bool add_cursor(LEX_STRING name);
+ bool add_cursor(const LEX_CSTRING *name, sp_pcontext *param_ctx,
+ class sp_lex_cursor *lex);
/// See comment for find_variable() above.
- bool find_cursor(LEX_STRING name, uint *poff, bool current_scope_only) const;
+ const sp_pcursor *find_cursor(const LEX_CSTRING *name,
+ uint *poff, bool current_scope_only) const;
+
+ const sp_pcursor *find_cursor_with_error(const LEX_CSTRING *name,
+ uint *poff,
+ bool current_scope_only) const
+ {
+ const sp_pcursor *pcursor= find_cursor(name, poff, current_scope_only);
+ if (!pcursor)
+ {
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name->str);
+ return NULL;
+ }
+ return pcursor;
+ }
+ /// Find cursor by offset (for SHOW {PROCEDURE|FUNCTION} CODE only).
+ const sp_pcursor *find_cursor(uint offset) const;
+
+ const sp_pcursor *get_cursor_by_local_frame_offset(uint offset) const
+ { return &m_cursors.at(offset); }
+
+ uint cursor_offset() const
+ { return m_cursor_offset; }
- /// Find cursor by offset (for debugging only).
- const LEX_STRING *find_cursor(uint offset) const;
+ uint frame_cursor_count() const
+ { return m_cursors.elements(); }
uint max_cursor_index() const
{ return m_max_cursor_index + m_cursors.elements(); }
@@ -481,6 +683,15 @@ public:
uint current_cursor_count() const
{ return m_cursor_offset + m_cursors.elements(); }
+ void set_for_loop(const Lex_for_loop_st &for_loop)
+ {
+ m_for_loop.init(for_loop);
+ }
+ const Lex_for_loop_st &for_loop()
+ {
+ return m_for_loop;
+ }
+
private:
/// Constructor for a tree node.
/// @param prev the parent parsing context
@@ -493,6 +704,8 @@ private:
sp_pcontext(const sp_pcontext &);
void operator=(sp_pcontext &);
+ sp_condition_value *find_predefined_condition(const LEX_CSTRING *name) const;
+
private:
/// m_max_var_index -- number of variables (including all types of arguments)
/// in this context including all children contexts.
@@ -538,19 +751,41 @@ private:
Dynamic_array<sp_condition *> m_conditions;
/// Stack of cursors.
- Dynamic_array<LEX_STRING> m_cursors;
+ Dynamic_array<sp_pcursor> m_cursors;
/// Stack of SQL-handlers.
Dynamic_array<sp_handler *> m_handlers;
- /// List of labels.
+ /*
+ In the below example the label <<lab>> has two meanings:
+ - GOTO lab : must go before the beginning of the loop
+ - CONTINUE lab : must go to the beginning of the loop
+ We solve this by storing block labels and goto labels into separate lists.
+
+ BEGIN
+ <<lab>>
+ FOR i IN a..10 LOOP
+ ...
+ GOTO lab;
+ ...
+ CONTINUE lab;
+ ...
+ END LOOP;
+ END;
+ */
+ /// List of block labels
List<sp_label> m_labels;
+ /// List of goto labels
+ List<sp_label> m_goto_labels;
/// Children contexts, used for destruction.
Dynamic_array<sp_pcontext *> m_children;
/// Scope of this parsing context.
enum_scope m_scope;
+
+ /// FOR LOOP characteristics
+ Lex_for_loop m_for_loop;
}; // class sp_pcontext : public Sql_alloc
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 6e724468966..3ceba42b0e4 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -26,6 +26,9 @@
#include "sp_rcontext.h"
#include "sp_pcontext.h"
#include "sql_select.h" // create_virtual_tmp_table
+#include "sql_base.h" // open_tables_only_view_structure
+#include "sql_acl.h" // SELECT_ACL
+#include "sql_parse.h" // check_table_access
///////////////////////////////////////////////////////////////////////////
// sp_rcontext implementation.
@@ -59,7 +62,8 @@ sp_rcontext::~sp_rcontext()
sp_rcontext *sp_rcontext::create(THD *thd,
const sp_pcontext *root_parsing_ctx,
- Field *return_value_fld)
+ Field *return_value_fld,
+ bool resolve_type_refs)
{
sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx,
return_value_fld,
@@ -68,9 +72,13 @@ sp_rcontext *sp_rcontext::create(THD *thd,
if (!ctx)
return NULL;
+ List<Spvar_definition> field_def_lst;
+ ctx->m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
+
if (ctx->alloc_arrays(thd) ||
- ctx->init_var_table(thd) ||
- ctx->init_var_items(thd))
+ (resolve_type_refs && ctx->resolve_type_refs(thd, field_def_lst)) ||
+ ctx->init_var_table(thd, field_def_lst) ||
+ ctx->init_var_items(thd, field_def_lst))
{
delete ctx;
return NULL;
@@ -102,28 +110,173 @@ bool sp_rcontext::alloc_arrays(THD *thd)
}
-bool sp_rcontext::init_var_table(THD *thd)
+bool sp_rcontext::init_var_table(THD *thd,
+ List<Spvar_definition> &field_def_lst)
{
- List<Column_definition> field_def_lst;
-
if (!m_root_parsing_ctx->max_var_index())
return false;
- m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
-
DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->max_var_index());
if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
return true;
- m_var_table->copy_blobs= true;
- m_var_table->alias.set("", 0, m_var_table->alias.charset());
+ return false;
+}
+
+/**
+ Check if we have access to use a column as a %TYPE reference.
+ @return false - OK
+ @return true - access denied
+*/
+static inline bool
+check_column_grant_for_type_ref(THD *thd, TABLE_LIST *table_list,
+ const char *str, size_t length)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ table_list->table->grant.want_privilege= SELECT_ACL;
+ return check_column_grant_in_table_ref(thd, table_list, str, length);
+#else
return false;
+#endif
+}
+
+
+/**
+ This method implementation is very close to fill_schema_table_by_open().
+*/
+bool sp_rcontext::resolve_type_ref(THD *thd, Column_definition *def,
+ Qualified_column_ident *ref)
+{
+ Open_tables_backup open_tables_state_backup;
+ thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
+
+ TABLE_LIST *table_list;
+ Field *src;
+ LEX *save_lex= thd->lex;
+ bool rc= true;
+
+ sp_lex_local lex(thd, thd->lex);
+ thd->lex= &lex;
+
+ lex.context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
+ // Make %TYPE variables see temporary tables that shadow permanent tables
+ thd->temporary_tables= open_tables_state_backup.temporary_tables;
+
+ if ((table_list= lex.select_lex.add_table_to_list(thd, ref, NULL, 0,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_READ)) &&
+ !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
+ !open_tables_only_view_structure(thd, table_list,
+ thd->mdl_context.has_locks()))
+ {
+ if ((src= lex.query_tables->table->find_field_by_name(&ref->m_column)))
+ {
+ if (!(rc= check_column_grant_for_type_ref(thd, table_list,
+ ref->m_column.str,
+ ref->m_column.length)))
+ {
+ *def= Column_definition(thd, src, NULL/*No defaults,no constraints*/);
+ def->flags&= (uint) ~NOT_NULL_FLAG;
+ rc= def->sp_prepare_create_field(thd, thd->mem_root);
+ }
+ }
+ else
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), ref->m_column.str, ref->table.str);
+ }
+
+ lex.unit.cleanup();
+ thd->temporary_tables= NULL; // Avoid closing temporary tables
+ close_thread_tables(thd);
+ thd->lex= save_lex;
+ thd->restore_backup_open_tables_state(&open_tables_state_backup);
+ return rc;
}
-bool sp_rcontext::init_var_items(THD *thd)
+/**
+ This method resolves the structure of a variable declared as:
+ rec t1%ROWTYPE;
+ It opens the table "t1" and copies its structure to %ROWTYPE variable.
+*/
+bool sp_rcontext::resolve_table_rowtype_ref(THD *thd,
+ Row_definition_list &defs,
+ Table_ident *ref)
+{
+ Open_tables_backup open_tables_state_backup;
+ thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
+
+ TABLE_LIST *table_list;
+ LEX *save_lex= thd->lex;
+ bool rc= true;
+
+ /*
+ Create a temporary LEX on stack and switch to it.
+ In case of VIEW, open_tables_only_view_structure() will open more
+ tables/views recursively. We want to avoid them to stick to the current LEX.
+ */
+ sp_lex_local lex(thd, thd->lex);
+ thd->lex= &lex;
+
+ lex.context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
+ // Make %ROWTYPE variables see temporary tables that shadow permanent tables
+ thd->temporary_tables= open_tables_state_backup.temporary_tables;
+
+ if ((table_list= lex.select_lex.add_table_to_list(thd, ref, NULL, 0,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_READ)) &&
+ !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) &&
+ !open_tables_only_view_structure(thd, table_list,
+ thd->mdl_context.has_locks()))
+ {
+ for (Field **src= lex.query_tables->table->field; *src; src++)
+ {
+ /*
+ Make field names on the THD memory root,
+ as the table will be closed and freed soon,
+ in the end of this method.
+ */
+ LEX_CSTRING tmp= src[0]->field_name;
+ Spvar_definition *def;
+ if ((rc= check_column_grant_for_type_ref(thd, table_list,
+ tmp.str, tmp.length)) ||
+ (rc= !(src[0]->field_name.str= thd->strmake(tmp.str, tmp.length))) ||
+ (rc= !(def= new (thd->mem_root) Spvar_definition(thd, *src))))
+ break;
+ src[0]->field_name.str= tmp.str; // Restore field name, just in case.
+ def->flags&= (uint) ~NOT_NULL_FLAG;
+ if ((rc= def->sp_prepare_create_field(thd, thd->mem_root)))
+ break;
+ defs.push_back(def, thd->mem_root);
+ }
+ }
+
+ lex.unit.cleanup();
+ thd->temporary_tables= NULL; // Avoid closing temporary tables
+ close_thread_tables(thd);
+ thd->lex= save_lex;
+ thd->restore_backup_open_tables_state(&open_tables_state_backup);
+ return rc;
+}
+
+
+bool sp_rcontext::resolve_type_refs(THD *thd, List<Spvar_definition> &defs)
+{
+ List_iterator<Spvar_definition> it(defs);
+ Spvar_definition *def;
+ while ((def= it++))
+ {
+ if (def->is_column_type_ref() &&
+ resolve_type_ref(thd, def, def->column_type_ref()))
+ return true;
+ }
+ return false;
+};
+
+
+bool sp_rcontext::init_var_items(THD *thd,
+ List<Spvar_definition> &field_def_lst)
{
uint num_vars= m_root_parsing_ctx->max_var_index();
@@ -135,34 +288,91 @@ bool sp_rcontext::init_var_items(THD *thd)
if (!m_var_items.array())
return true;
- for (uint idx = 0; idx < num_vars; ++idx)
+ DBUG_ASSERT(field_def_lst.elements == num_vars);
+ List_iterator<Spvar_definition> it(field_def_lst);
+ Spvar_definition *def= it++;
+
+ for (uint idx= 0; idx < num_vars; ++idx, def= it++)
{
- if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, m_var_table->field[idx])))
- return true;
+ Field *field= m_var_table->field[idx];
+ if (def->is_table_rowtype_ref())
+ {
+ Row_definition_list defs;
+ Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
+ if (!(m_var_items[idx]= item) ||
+ resolve_table_rowtype_ref(thd, defs, def->table_rowtype_ref()) ||
+ item->row_create_items(thd, &defs))
+ return true;
+ }
+ else if (def->is_cursor_rowtype_ref())
+ {
+ Row_definition_list defs;
+ Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
+ if (!(m_var_items[idx]= item))
+ return true;
+ }
+ else if (def->is_row())
+ {
+ Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
+ if (!(m_var_items[idx]= item) ||
+ item->row_create_items(thd, def->row_field_definitions()))
+ return true;
+ }
+ else
+ {
+ if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, field)))
+ return true;
+ }
}
+ return false;
+}
+
+bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
+{
+ DBUG_ASSERT(list);
+ if (!(m_table= create_virtual_tmp_table(thd, *list)))
+ return true;
+
+ if (alloc_arguments(thd, list->elements))
+ return true;
+
+ List_iterator<Spvar_definition> it(*list);
+ Spvar_definition *def;
+ for (arg_count= 0; (def= it++); arg_count++)
+ {
+ if (!(args[arg_count]= new (thd->mem_root)
+ Item_field(thd, m_table->field[arg_count])))
+ return true;
+ }
return false;
}
+Item_spvar_args::~Item_spvar_args()
+{
+ if (m_table)
+ free_blobs(m_table);
+}
+
+
bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
{
DBUG_ASSERT(m_return_value_fld);
m_return_value_set = true;
- return sp_eval_expr(thd, m_return_value_fld, return_value_item);
+ return sp_eval_expr(thd, NULL, m_return_value_fld, return_value_item);
}
-bool sp_rcontext::push_cursor(THD *thd, sp_lex_keeper *lex_keeper,
- sp_instr_cpush *i)
+bool sp_rcontext::push_cursor(THD *thd, sp_lex_keeper *lex_keeper)
{
/*
We should create cursors in the callers arena, as
it could be (and usually is) used in several instructions.
*/
- sp_cursor *c= new (callers_arena->mem_root) sp_cursor(thd, lex_keeper, i);
+ sp_cursor *c= new (callers_arena->mem_root) sp_cursor(thd, lex_keeper);
if (c == NULL)
return true;
@@ -228,9 +438,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
if (thd->is_error())
{
found_handler=
- cur_spi->m_ctx->find_handler(da->get_sqlstate(),
- da->sql_errno(),
- Sql_condition::WARN_LEVEL_ERROR);
+ cur_spi->m_ctx->find_handler(da->get_error_condition_identity());
if (found_handler)
found_condition= da->get_error_condition();
@@ -244,12 +452,10 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
*/
if (!found_condition)
{
- Sql_condition *condition=
- new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root);
- condition->set(da->sql_errno(), da->get_sqlstate(),
- Sql_condition::WARN_LEVEL_ERROR,
- da->message());
- found_condition= condition;
+ found_condition=
+ new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root,
+ da->get_error_condition_identity(),
+ da->message());
}
}
else if (da->current_statement_warn_count())
@@ -266,10 +472,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
if (c->get_level() == Sql_condition::WARN_LEVEL_WARN ||
c->get_level() == Sql_condition::WARN_LEVEL_NOTE)
{
- const sp_handler *handler=
- cur_spi->m_ctx->find_handler(c->get_sqlstate(),
- c->get_sql_errno(),
- c->get_level());
+ const sp_handler *handler= cur_spi->m_ctx->find_handler(*c);
if (handler)
{
found_handler= handler;
@@ -367,15 +570,102 @@ uint sp_rcontext::exit_handler(Diagnostics_area *da)
}
-int sp_rcontext::set_variable(THD *thd, Field *field, Item **value)
+int sp_rcontext::set_variable(THD *thd, uint idx, Item **value)
{
+ Field *field= m_var_table->field[idx];
if (!value)
{
field->set_null();
return 0;
}
+ Item *dst= m_var_items[idx];
+
+ if (dst->cmp_type() != ROW_RESULT)
+ return sp_eval_expr(thd, dst, m_var_table->field[idx], value);
+
+ DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
+ if (value[0]->type() == Item::NULL_ITEM)
+ {
+ /*
+ We're in a auto-generated sp_inst_set, to assign
+ the explicit default NULL value to a ROW variable.
+ */
+ for (uint i= 0; i < dst->cols(); i++)
+ {
+ Item_field_row *item_field_row= (Item_field_row*) dst;
+ item_field_row->get_row_field(i)->set_null();
+ }
+ return false;
+ }
+
+ /**
+ - In case if we're assigning a ROW variable from another ROW variable,
+ value[0] points to Item_splocal. sp_prepare_func_item() will return the
+ fixed underlying Item_field_spvar with ROW members in its aguments().
+ - In case if we're assigning from a ROW() value, src and value[0] will
+ point to the same Item_row.
+ */
+ Item *src;
+ if (!(src= sp_prepare_func_item(thd, value, dst->cols())) ||
+ src->cmp_type() != ROW_RESULT)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), dst->cols());
+ return true;
+ }
+ DBUG_ASSERT(dst->cols() == src->cols());
+ for (uint i= 0; i < src->cols(); i++)
+ set_variable_row_field(thd, idx, i, src->addr(i));
+ return false;
+}
+
+
+void sp_rcontext::set_variable_row_field_to_null(THD *thd,
+ uint var_idx,
+ uint field_idx)
+{
+ Item *dst= get_item(var_idx);
+ DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
+ DBUG_ASSERT(dst->cmp_type() == ROW_RESULT);
+ Item_field_row *item_field_row= (Item_field_row*) dst;
+ item_field_row->get_row_field(field_idx)->set_null();
+}
+
+
+int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
+ Item **value)
+{
+ DBUG_ASSERT(value);
+ Item *dst= get_item(var_idx);
+ DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
+ DBUG_ASSERT(dst->cmp_type() == ROW_RESULT);
+ Item_field_row *item_field_row= (Item_field_row*) dst;
+
+ Item *expr_item= sp_prepare_func_item(thd, value);
+ if (!expr_item)
+ {
+ DBUG_ASSERT(thd->is_error());
+ return true;
+ }
+ return sp_eval_expr(thd,
+ item_field_row->arguments()[field_idx],
+ item_field_row->get_row_field(field_idx),
+ value);
+}
- return sp_eval_expr(thd, field, value);
+
+int sp_rcontext::set_variable_row(THD *thd, uint var_idx, List<Item> &items)
+{
+ DBUG_ENTER("sp_rcontext::set_variable_row");
+ DBUG_ASSERT(thd->spcont->get_item(var_idx)->cols() == items.elements);
+ List_iterator<Item> it(items);
+ Item *item;
+ for (uint i= 0 ; (item= it++) ; i++)
+ {
+ int rc;
+ if ((rc= thd->spcont->set_variable_row_field(thd, var_idx, i, &item)))
+ DBUG_RETURN(rc);
+ }
+ DBUG_RETURN(0);
}
@@ -387,7 +677,7 @@ Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
thd->set_n_backup_active_arena(thd->spcont->callers_arena, &current_arena);
- holder= Item_cache::get_cache(thd, item);
+ holder= item->get_cache(thd);
thd->restore_active_arena(thd->spcont->callers_arena, &current_arena);
@@ -421,11 +711,13 @@ bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
///////////////////////////////////////////////////////////////////////////
-sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, sp_instr_cpush *i):
+sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper):
result(thd_arg),
m_lex_keeper(lex_keeper),
server_side_cursor(NULL),
- m_i(i)
+ m_fetch_count(0),
+ m_row_count(0),
+ m_found(false)
{
/*
currsor can't be stored in QC, so we should prevent opening QC for
@@ -462,6 +754,27 @@ int sp_cursor::open(THD *thd)
}
+/**
+ Open the cursor, but do not copy data.
+ This method is used to fetch the cursor structure
+ to cursor%ROWTYPE routine variables.
+ Data copying is suppressed by setting thd->lex->limit_rows_examined to 0.
+*/
+int sp_cursor::open_view_structure_only(THD *thd)
+{
+ int res;
+ int thd_no_errors_save= thd->no_errors;
+ Item *limit_rows_examined= thd->lex->limit_rows_examined; // No data copying
+ if (!(thd->lex->limit_rows_examined= new (thd->mem_root) Item_uint(thd, 0)))
+ return -1;
+ thd->no_errors= true; // Suppress ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT
+ res= open(thd);
+ thd->no_errors= thd_no_errors_save;
+ thd->lex->limit_rows_examined= limit_rows_examined;
+ return res;
+}
+
+
int sp_cursor::close(THD *thd)
{
if (! server_side_cursor)
@@ -470,6 +783,8 @@ int sp_cursor::close(THD *thd)
MYF(0));
return -1;
}
+ m_row_count= m_fetch_count= 0;
+ m_found= false;
destroy();
return 0;
}
@@ -490,13 +805,17 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
MYF(0));
return -1;
}
- if (vars->elements != result.get_field_count())
+ if (vars->elements != result.get_field_count() &&
+ (vars->elements != 1 ||
+ result.get_field_count() !=
+ thd->spcont->get_item(vars->head()->offset)->cols()))
{
my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
ER_THD(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
return -1;
}
+ m_fetch_count++;
DBUG_EXECUTE_IF("bug23032_emit_warning",
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_ERROR,
@@ -514,14 +833,24 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
*/
if (! server_side_cursor->is_open())
{
+ m_found= false;
+ if (thd->variables.sql_mode & MODE_ORACLE)
+ return 0;
my_message(ER_SP_FETCH_NO_DATA, ER_THD(thd, ER_SP_FETCH_NO_DATA), MYF(0));
return -1;
}
+ m_found= true;
+ m_row_count++;
return 0;
}
+bool sp_cursor::export_structure(THD *thd, Row_definition_list *list)
+{
+ return server_side_cursor->export_structure(thd, list);
+}
+
///////////////////////////////////////////////////////////////////////////
// sp_cursor::Select_fetch_into_spvars implementation.
///////////////////////////////////////////////////////////////////////////
@@ -539,15 +868,16 @@ int sp_cursor::Select_fetch_into_spvars::prepare(List<Item> &fields,
}
-int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
+bool sp_cursor::Select_fetch_into_spvars::
+ send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items)
{
- List_iterator_fast<sp_variable> spvar_iter(*spvar_list);
+ List_iterator_fast<sp_variable> spvar_iter(vars);
List_iterator_fast<Item> item_iter(items);
sp_variable *spvar;
Item *item;
/* Must be ensured by the caller */
- DBUG_ASSERT(spvar_list->elements == items.elements);
+ DBUG_ASSERT(vars.elements == items.elements);
/*
Assign the row fetched from a server side cursor to stored
@@ -560,3 +890,25 @@ int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
}
return false;
}
+
+
+int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
+{
+ Item *item;
+ /*
+ If we have only one variable in spvar_list, and this is a ROW variable,
+ and the number of fields in the ROW variable matches the number of
+ fields in the query result, we fetch to this ROW variable.
+
+ If there is one variable, and it is a ROW variable, but its number
+ of fields does not match the number of fields in the query result,
+ we go through send_data_to_variable_list(). It will report an error
+ on attempt to assign a scalar value to a ROW variable.
+ */
+ return spvar_list->elements == 1 &&
+ (item= thd->spcont->get_item(spvar_list->head()->offset)) &&
+ item->type_handler() == &type_handler_row &&
+ item->cols() == items.elements ?
+ thd->spcont->set_variable_row(thd, spvar_list->head()->offset, items) :
+ send_data_to_variable_list(*spvar_list, items);
+}
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 2640490fefa..98464518787 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -70,7 +70,8 @@ public:
/// @return valid sp_rcontext object or NULL in case of OOM-error.
static sp_rcontext *create(THD *thd,
const sp_pcontext *root_parsing_ctx,
- Field *return_value_fld);
+ Field *return_value_fld,
+ bool resolve_type_refs);
~sp_rcontext();
@@ -120,18 +121,10 @@ public:
/// standard SQL-condition processing (Diagnostics_area should contain an
/// object for active SQL-condition, not just information stored in DA's
/// fields).
- class Sql_condition_info : public Sql_alloc
+ class Sql_condition_info : public Sql_alloc,
+ public Sql_condition_identity
{
public:
- /// SQL error code.
- uint sql_errno;
-
- /// Error level.
- Sql_condition::enum_warning_level level;
-
- /// SQLSTATE.
- char sql_state[SQLSTATE_LENGTH + 1];
-
/// Text message.
char *message;
@@ -141,12 +134,8 @@ public:
/// @param arena Query arena for SP
Sql_condition_info(const Sql_condition *_sql_condition,
Query_arena *arena)
- :sql_errno(_sql_condition->get_sql_errno()),
- level(_sql_condition->get_level())
+ :Sql_condition_identity(*_sql_condition)
{
- memcpy(sql_state, _sql_condition->get_sqlstate(), SQLSTATE_LENGTH);
- sql_state[SQLSTATE_LENGTH]= '\0';
-
message= strdup_root(arena->mem_root, _sql_condition->get_message_text());
}
};
@@ -197,9 +186,11 @@ public:
// SP-variables.
/////////////////////////////////////////////////////////////////////////
- int set_variable(THD *thd, uint var_idx, Item **value)
- { return set_variable(thd, m_var_table->field[var_idx], value); }
-
+ int set_variable(THD *thd, uint var_idx, Item **value);
+ void set_variable_row_field_to_null(THD *thd, uint var_idx, uint field_idx);
+ int set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
+ Item **value);
+ int set_variable_row(THD *thd, uint var_idx, List<Item> &items);
Item *get_item(uint var_idx) const
{ return m_var_items[var_idx]; }
@@ -281,7 +272,7 @@ public:
/// @return error flag.
/// @retval false on success.
/// @retval true on error.
- bool push_cursor(THD *thd, sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
+ bool push_cursor(THD *thd, sp_lex_keeper *lex_keeper);
/// Pop and delete given number of sp_cursor instance from the cursor stack.
///
@@ -346,7 +337,13 @@ private:
/// @return error flag.
/// @retval false on success.
/// @retval true on error.
- bool init_var_table(THD *thd);
+ bool init_var_table(THD *thd, List<Spvar_definition> &defs);
+
+ bool resolve_type_refs(THD *, List<Spvar_definition> &defs);
+ bool resolve_type_ref(THD *thd, Column_definition *def,
+ Qualified_column_ident *ref);
+ bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs,
+ Table_ident *ref);
/// Create and initialize an Item-adapter (Item_field) for each SP-var field.
///
@@ -355,7 +352,7 @@ private:
/// @return error flag.
/// @retval false on success.
/// @retval true on error.
- bool init_var_items(THD *thd);
+ bool init_var_items(THD *thd, List<Spvar_definition> &defs);
/// Create an instance of appropriate Item_cache class depending on the
/// specified type in the callers arena.
@@ -369,8 +366,6 @@ private:
/// @return Pointer to valid object on success, or NULL in case of error.
Item_cache *create_case_expr_holder(THD *thd, const Item *item) const;
- int set_variable(THD *thd, Field *field, Item **value);
-
private:
/// Top-level (root) parsing context for this runtime context.
const sp_pcontext *m_root_parsing_ctx;
@@ -427,6 +422,7 @@ private:
{
List<sp_variable> *spvar_list;
uint field_count;
+ bool send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items);
public:
Select_fetch_into_spvars(THD *thd_arg): select_result_interceptor(thd_arg) {}
uint get_field_count() { return field_count; }
@@ -438,7 +434,7 @@ private:
};
public:
- sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
+ sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper);
virtual ~sp_cursor()
{ destroy(); }
@@ -447,21 +443,33 @@ public:
int open(THD *thd);
+ int open_view_structure_only(THD *thd);
+
int close(THD *thd);
my_bool is_open()
{ return MY_TEST(server_side_cursor); }
+ bool found() const
+ { return m_found; }
+
+ ulonglong row_count() const
+ { return m_row_count; }
+
+ ulonglong fetch_count() const
+ { return m_fetch_count; }
+
int fetch(THD *, List<sp_variable> *vars);
- sp_instr_cpush *get_instr()
- { return m_i; }
+ bool export_structure(THD *thd, Row_definition_list *list);
private:
Select_fetch_into_spvars result;
sp_lex_keeper *m_lex_keeper;
Server_side_cursor *server_side_cursor;
- sp_instr_cpush *m_i; // My push instruction
+ ulonglong m_fetch_count; // Number of FETCH commands since last OPEN
+ ulonglong m_row_count; // Number of successful FETCH since last OPEN
+ bool m_found; // If last FETCH fetched a row
void destroy();
}; // class sp_cursor : public Sql_alloc
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 77f502d3a7b..79acb996740 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -176,30 +176,30 @@ TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
const TABLE_FIELD_DEF
mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields, 0, (uint*) 0 };
-static LEX_STRING native_password_plugin_name= {
- C_STRING_WITH_LEN("mysql_native_password")
+static LEX_CSTRING native_password_plugin_name= {
+ STRING_WITH_LEN("mysql_native_password")
};
-static LEX_STRING old_password_plugin_name= {
- C_STRING_WITH_LEN("mysql_old_password")
+static LEX_CSTRING old_password_plugin_name= {
+ STRING_WITH_LEN("mysql_old_password")
};
/// @todo make it configurable
-LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
+LEX_CSTRING *default_auth_plugin_name= &native_password_plugin_name;
/*
Wildcard host, matches any hostname
*/
-LEX_STRING host_not_specified= { C_STRING_WITH_LEN("%") };
+LEX_CSTRING host_not_specified= { STRING_WITH_LEN("%") };
/*
Constants, used in the SHOW GRANTS command.
Their actual string values are irrelevant, they're always compared
as pointers to these string constants.
*/
-LEX_STRING current_user= { C_STRING_WITH_LEN("*current_user") };
-LEX_STRING current_role= { C_STRING_WITH_LEN("*current_role") };
-LEX_STRING current_user_and_current_role= { C_STRING_WITH_LEN("*current_user_and_current_role") };
+LEX_CSTRING current_user= { STRING_WITH_LEN("*current_user") };
+LEX_CSTRING current_role= { STRING_WITH_LEN("*current_role") };
+LEX_CSTRING current_user_and_current_role= { STRING_WITH_LEN("*current_user_and_current_role") };
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -244,7 +244,7 @@ public:
{ return (void*) alloc_root(mem_root, size); }
uchar flags; // field used to store various state information
- LEX_STRING user;
+ LEX_CSTRING user;
/* list to hold references to granted roles (ACL_ROLE instances) */
DYNAMIC_ARRAY role_grants;
};
@@ -259,9 +259,9 @@ public:
uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 4.0, 20 - 4.1.1
enum SSL_type ssl_type;
const char *ssl_cipher, *x509_issuer, *x509_subject;
- LEX_STRING plugin;
- LEX_STRING auth_string;
- LEX_STRING default_rolename;
+ LEX_CSTRING plugin;
+ LEX_CSTRING auth_string;
+ LEX_CSTRING default_rolename;
ACL_USER *copy(MEM_ROOT *root)
{
@@ -338,7 +338,7 @@ class ACL_DB :public ACL_ACCESS
{
public:
acl_host_and_ip host;
- char *user,*db;
+ const char *user,*db;
ulong initial_access; /* access bits present in the table */
};
@@ -530,10 +530,10 @@ public:
}
static int store_pk(TABLE *table,
- const LEX_STRING *host,
- const LEX_STRING *user,
- const LEX_STRING *proxied_host,
- const LEX_STRING *proxied_user)
+ const LEX_CSTRING *host,
+ const LEX_CSTRING *user,
+ const LEX_CSTRING *proxied_host,
+ const LEX_CSTRING *proxied_user)
{
DBUG_ENTER("ACL_PROXY_USER::store_pk");
DBUG_PRINT("info", ("host=%s, user=%s, proxied_host=%s, proxied_user=%s",
@@ -560,10 +560,10 @@ public:
}
static int store_data_record(TABLE *table,
- const LEX_STRING *host,
- const LEX_STRING *user,
- const LEX_STRING *proxied_host,
- const LEX_STRING *proxied_user,
+ const LEX_CSTRING *host,
+ const LEX_CSTRING *user,
+ const LEX_CSTRING *proxied_host,
+ const LEX_CSTRING *proxied_user,
bool with_grant,
const char *grantor)
{
@@ -616,8 +616,8 @@ struct ROLE_GRANT_PAIR : public Sql_alloc
LEX_STRING hashkey;
bool with_admin;
- bool init(MEM_ROOT *mem, char *username, char *hostname, char *rolename,
- bool with_admin_option);
+ bool init(MEM_ROOT *mem, const char *username, const char *hostname,
+ const char *rolename, bool with_admin_option);
};
static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length,
@@ -627,8 +627,8 @@ static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length,
return (uchar*) entry->hashkey.str;
}
-bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username,
- char *hostname, char *rolename,
+bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, const char *username,
+ const char *hostname, const char *rolename,
bool with_admin_option)
{
size_t uname_l = safe_strlen(username);
@@ -736,7 +736,7 @@ static void rebuild_role_grants(void);
static ACL_USER *find_user_exact(const char *host, const char *user);
static ACL_USER *find_user_wild(const char *host, const char *user, const char *ip= 0);
static ACL_ROLE *find_acl_role(const char *user);
-static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u, const LEX_STRING *h, const LEX_STRING *r);
+static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u, const LEX_CSTRING *h, const LEX_CSTRING *r);
static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host);
static bool update_user_table(THD *, const User_table &, const char *, const char *, const
char *, uint);
@@ -1487,7 +1487,7 @@ static bool has_validation_plugins()
MariaDB_PASSWORD_VALIDATION_PLUGIN, NULL);
}
-struct validation_data { LEX_STRING *user, *password; };
+struct validation_data { LEX_CSTRING *user, *password; };
static my_bool do_validate(THD *, plugin_ref plugin, void *arg)
{
@@ -1504,7 +1504,7 @@ static bool validate_password(LEX_USER *user, THD *thd)
{
struct validation_data data= { &user->user,
user->pwtext.str ? &user->pwtext :
- const_cast<LEX_STRING *>(&empty_lex_str) };
+ const_cast<LEX_CSTRING *>(&empty_clex_str) };
if (plugin_foreach(NULL, do_validate,
MariaDB_PASSWORD_VALIDATION_PLUGIN, &data))
{
@@ -1553,7 +1553,7 @@ set_user_salt(ACL_USER *acl_user, const char *password, uint password_len)
acl_user->salt_len= 0;
}
-static char *fix_plugin_ptr(char *name)
+static const char *fix_plugin_ptr(const char *name)
{
if (my_strcasecmp(system_charset_info, name,
native_password_plugin_name.str) == 0)
@@ -1645,13 +1645,13 @@ static bool fix_lex_user(THD *thd, LEX_USER *user)
if (user->plugin.length)
{
user->pwhash= user->auth;
- user->plugin= empty_lex_str;
- user->auth= empty_lex_str;
+ user->plugin= empty_clex_str;
+ user->auth= empty_clex_str;
}
if (user->pwhash.length && user->pwhash.length != check_length)
{
- my_error(ER_PASSWD_LENGTH, MYF(0), check_length);
+ my_error(ER_PASSWD_LENGTH, MYF(0), (int) check_length);
return true;
}
@@ -2138,12 +2138,13 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_DB db;
+ char *db_name;
db.user=get_field(&acl_memroot, db_table.user());
const char *hostname= get_field(&acl_memroot, db_table.host());
if (!hostname && find_acl_role(db.user))
hostname= "";
update_hostname(&db.host, hostname);
- db.db=get_field(&acl_memroot, db_table.db());
+ db.db= db_name= get_field(&acl_memroot, db_table.db());
if (!db.db)
{
sql_print_warning("Found an entry in the 'db' table with empty database name; Skipped");
@@ -2171,8 +2172,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
sql_print_warning(ER_THD(thd, ER_WRONG_DB_NAME), db.db);
continue;
}
- my_casedn_str(files_charset_info, db.db);
- if (strcmp(db.db, tmp_name) != 0)
+ my_casedn_str(files_charset_info, db_name);
+ if (strcmp(db_name, tmp_name) != 0)
{
sql_print_warning("'db' entry '%s %s@%s' had database in mixed "
"case that has been forced to lowercase because "
@@ -2496,8 +2497,8 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
TRUE Error
*/
-bool acl_getroot(Security_context *sctx, char *user, char *host,
- char *ip, char *db)
+bool acl_getroot(Security_context *sctx, const char *user, const char *host,
+ const char *ip, const char *db)
{
int res= 1;
uint i;
@@ -2610,7 +2611,7 @@ static int check_user_can_set_role(const char *user, const char *host,
acl_user= find_user_wild(host, user, ip);
if (acl_user == NULL)
{
- my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
+ my_error(ER_INVALID_CURRENT_USER, MYF(0));
result= -1;
}
else if (access)
@@ -2660,7 +2661,7 @@ end:
}
-int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
+int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access)
{
/* Yes! priv_user@host. Don't ask why - that's what check_access() does. */
return check_user_can_set_role(thd->security_ctx->priv_user,
@@ -2668,7 +2669,7 @@ int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
}
-int acl_setrole(THD *thd, char *rolename, ulonglong access)
+int acl_setrole(THD *thd, const char *rolename, ulonglong access)
{
/* merge the privileges */
Security_context *sctx= thd->security_ctx;
@@ -2714,8 +2715,8 @@ static void acl_update_user(const char *user, const char *host,
const char *x509_subject,
USER_RESOURCES *mqh,
ulong privileges,
- const LEX_STRING *plugin,
- const LEX_STRING *auth)
+ const LEX_CSTRING *plugin,
+ const LEX_CSTRING *auth)
{
mysql_mutex_assert_owner(&acl_cache->lock);
@@ -2792,8 +2793,8 @@ static void acl_insert_user(const char *user, const char *host,
const char *x509_subject,
USER_RESOURCES *mqh,
ulong privileges,
- const LEX_STRING *plugin,
- const LEX_STRING *auth)
+ const LEX_CSTRING *plugin,
+ const LEX_CSTRING *auth)
{
ACL_USER acl_user;
@@ -3998,7 +3999,7 @@ static int replace_user_table(THD *thd, const User_table &user_table,
}
}
else
- combo.pwhash= empty_lex_str;
+ combo.pwhash= empty_clex_str;
/* if the user table is not up to date, we can't handle role updates */
if (!user_table.is_role() && handle_as_role)
@@ -4401,8 +4402,8 @@ abort:
@param revoke_grant true for REVOKE, false for GRANT
*/
static int
-replace_roles_mapping_table(TABLE *table, LEX_STRING *user, LEX_STRING *host,
- LEX_STRING *role, bool with_admin,
+replace_roles_mapping_table(TABLE *table, LEX_CSTRING *user, LEX_CSTRING *host,
+ LEX_CSTRING *role, bool with_admin,
ROLE_GRANT_PAIR *existing, bool revoke_grant)
{
DBUG_ENTER("replace_roles_mapping_table");
@@ -4483,7 +4484,7 @@ table_error:
@param revoke_grant true for REVOKE, false for GRANT
*/
static int
-update_role_mapping(LEX_STRING *user, LEX_STRING *host, LEX_STRING *role,
+update_role_mapping(LEX_CSTRING *user, LEX_CSTRING *host, LEX_CSTRING *role,
bool with_admin, ROLE_GRANT_PAIR *existing, bool revoke_grant)
{
if (revoke_grant)
@@ -5823,7 +5824,8 @@ static int db_name_sort(ACL_DB * const *db1, ACL_DB * const *db2)
2 - ACL_DB was added
4 - ACL_DB was deleted
*/
-static int update_role_db(ACL_DB *merged, ACL_DB **first, ulong access, char *role)
+static int update_role_db(ACL_DB *merged, ACL_DB **first, ulong access,
+ const char *role)
{
if (!first)
return 0;
@@ -6043,8 +6045,8 @@ static int update_role_columns(GRANT_TABLE *merged,
4 - GRANT_TABLE was deleted
*/
static int update_role_table_columns(GRANT_TABLE *merged,
- GRANT_TABLE **first, GRANT_TABLE **last,
- ulong privs, ulong cols, char *role)
+ GRANT_TABLE **first, GRANT_TABLE **last,
+ ulong privs, ulong cols, const char *role)
{
if (!first)
return 0;
@@ -6173,7 +6175,7 @@ static int routine_name_sort(GRANT_NAME * const *r1, GRANT_NAME * const *r2)
4 - GRANT_NAME was deleted
*/
static int update_role_routines(GRANT_NAME *merged, GRANT_NAME **first,
- ulong privs, char *role, HASH *hash)
+ ulong privs, const char *role, HASH *hash)
{
if (!first)
return 0;
@@ -6392,7 +6394,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
List_iterator <LEX_USER> str_list (user_list);
LEX_USER *Str, *tmp_Str;
bool create_new_users=0;
- char *db_name, *table_name;
+ const char *db_name, *table_name;
DBUG_ENTER("mysql_table_grant");
if (rights & ~TABLE_ACLS)
@@ -6438,7 +6440,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
if (!(rights & CREATE_ACL))
{
- if (!ha_table_exists(thd, table_list->db, table_list->table_name, 0))
+ if (!ha_table_exists(thd, table_list->db, table_list->table_name))
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
DBUG_RETURN(TRUE);
@@ -6642,7 +6644,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
List_iterator <LEX_USER> str_list (user_list);
LEX_USER *Str, *tmp_Str;
bool create_new_users= 0, result;
- char *db_name, *table_name;
+ const char *db_name, *table_name;
DBUG_ENTER("mysql_routine_grant");
if (rights & ~PROC_ACLS)
@@ -6752,7 +6754,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
append a user or role name to a buffer that will be later used as an error message
*/
static void append_user(THD *thd, String *str,
- const LEX_STRING *u, const LEX_STRING *h)
+ const LEX_CSTRING *u, const LEX_CSTRING *h)
{
if (str->length())
str->append(',');
@@ -6795,11 +6797,11 @@ static int can_grant_role_callback(ACL_USER_BASE *grantee,
return 0; // keep searching
if (grantee->flags & IS_ROLE)
- pair= find_role_grant_pair(&grantee->user, &empty_lex_str, &role->user);
+ pair= find_role_grant_pair(&grantee->user, &empty_clex_str, &role->user);
else
{
ACL_USER *user= (ACL_USER *)grantee;
- LEX_STRING host= { user->host.hostname, user->hostname_length };
+ LEX_CSTRING host= { user->host.hostname, user->hostname_length };
pair= find_role_grant_pair(&user->user, &host, &role->user);
}
if (!pair->with_admin)
@@ -6844,9 +6846,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
bool create_new_user, no_auto_create_user;
String wrong_users;
LEX_USER *user, *granted_role;
- LEX_STRING rolename;
- LEX_STRING username;
- LEX_STRING hostname;
+ LEX_CSTRING rolename;
+ LEX_CSTRING username;
+ LEX_CSTRING hostname;
ACL_ROLE *role, *role_as_user;
List_iterator <LEX_USER> user_list(list);
@@ -6900,9 +6902,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
}
if (!(role_as_user= find_acl_role(thd->security_ctx->priv_role)))
{
- LEX_STRING ls= { thd->security_ctx->priv_role,
- strlen(thd->security_ctx->priv_role) };
- append_user(thd, &wrong_users, &ls, &empty_lex_str);
+ LEX_CSTRING ls= { thd->security_ctx->priv_role,
+ strlen(thd->security_ctx->priv_role) };
+ append_user(thd, &wrong_users, &ls, &empty_clex_str);
result= 1;
continue;
}
@@ -6910,13 +6912,13 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
/* can not grant current_role to current_role */
if (granted_role->user.str == current_role.str)
{
- append_user(thd, &wrong_users, &role_as_user->user, &empty_lex_str);
+ append_user(thd, &wrong_users, &role_as_user->user, &empty_clex_str);
result= 1;
continue;
}
username.str= thd->security_ctx->priv_role;
username.length= strlen(username.str);
- hostname= empty_lex_str;
+ hostname= empty_clex_str;
}
else if (user->user.str == current_user.str)
{
@@ -6932,12 +6934,12 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
hostname= user->host;
else
if ((role_as_user= find_acl_role(user->user.str)))
- hostname= empty_lex_str;
+ hostname= empty_clex_str;
else
{
if (is_invalid_role_name(username.str))
{
- append_user(thd, &wrong_users, &username, &empty_lex_str);
+ append_user(thd, &wrong_users, &username, &empty_clex_str);
result= 1;
continue;
}
@@ -6999,7 +7001,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
if (role_as_user &&
traverse_role_graph_down(role, 0, 0, 0) == ROLE_CYCLE_FOUND)
{
- append_user(thd, &wrong_users, &username, &empty_lex_str);
+ append_user(thd, &wrong_users, &username, &empty_clex_str);
result= 1;
undo_add_role_user_mapping(grantee, role);
continue;
@@ -7034,7 +7036,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
thd->lex->with_admin_option,
hash_entry, revoke))
{
- append_user(thd, &wrong_users, &username, &empty_lex_str);
+ append_user(thd, &wrong_users, &username, &empty_clex_str);
result= 1;
if (!revoke)
{
@@ -7522,7 +7524,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
Security_context *sctx= thd->security_ctx;
uint i;
- ulong orig_want_access= want_access;
+ ulong original_want_access= want_access;
bool locked= 0;
GRANT_TABLE *grant_table;
GRANT_TABLE *grant_table_role= NULL;
@@ -7556,6 +7558,16 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *const t_ref=
tl->correspondent_table ? tl->correspondent_table : tl;
sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx;
+ ulong orig_want_access= original_want_access;
+
+ if (t_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ orig_want_access= ((t_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal,
@@ -7887,7 +7899,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg,
for (; !fields->end_of_fields(); fields->next())
{
- const char *field_name= fields->name();
+ LEX_CSTRING *field_name= fields->name();
if (table_name != fields->get_table_name())
{
@@ -7924,16 +7936,15 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg,
if (grant_table)
{
GRANT_COLUMN *grant_column=
- column_hash_search(grant_table, field_name,
- (uint) strlen(field_name));
+ column_hash_search(grant_table, field_name->str, field_name->length);
if (grant_column)
have_access= grant_column->rights;
}
if (grant_table_role)
{
GRANT_COLUMN *grant_column=
- column_hash_search(grant_table_role, field_name,
- (uint) strlen(field_name));
+ column_hash_search(grant_table_role, field_name->str,
+ field_name->length);
if (grant_column)
have_access|= grant_column->rights;
}
@@ -7965,7 +7976,7 @@ err:
command,
sctx->priv_user,
sctx->host_or_ip,
- fields->name(),
+ fields->name()->str,
table_name);
return 1;
}
@@ -8466,8 +8477,9 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role)
that a role can never happen here, so *rolename will never
be assigned to
*/
-static bool check_show_access(THD *thd, LEX_USER *lex_user, char **username,
- char **hostname, char **rolename)
+static bool check_show_access(THD *thd, LEX_USER *lex_user,
+ const char **username,
+ const char **hostname, const char **rolename)
{
DBUG_ENTER("check_show_access");
@@ -8516,26 +8528,26 @@ static bool check_show_access(THD *thd, LEX_USER *lex_user, char **username,
bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
{
- char *username= NULL, *hostname= NULL;
+ const char *username= NULL, *hostname= NULL;
char buff[1024]; //Show create user should not take more than 1024 bytes.
Protocol *protocol= thd->protocol;
bool error= false;
ACL_USER *acl_user;
+ uint head_length;
DBUG_ENTER("mysql_show_create_user");
if (check_show_access(thd, lex_user, &username, &hostname, NULL))
DBUG_RETURN(TRUE);
List<Item> field_list;
- strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS);
+ head_length= (uint) (strxmov(buff, "CREATE USER for ", username, "@",
+ hostname, NullS) - buff);
Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0);
if (!field)
- {
- my_error(ER_OUTOFMEMORY, MYF(0));
DBUG_RETURN(true);
- }
- field->name= buff;
+ field->name.str= buff;
+ field->name.length= head_length;
field->max_length= sizeof(buff);
field_list.push_back(field, thd->mem_root);
if (protocol->send_result_set_metadata(&field_list,
@@ -8590,10 +8602,12 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data)
}
void mysql_show_grants_get_fields(THD *thd, List<Item> *fields,
- const char *name)
+ const char *name, size_t length)
{
Item_string *field=new (thd->mem_root) Item_string_ascii(thd, "", 0);
- field->name= (char *) name;
+ /* Set name explicit to avoid character set conversions */
+ field->name.str= name;
+ field->name.length= length;
field->max_length=1024;
fields->push_back(field, thd->mem_root);
}
@@ -8613,7 +8627,7 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
ACL_ROLE *acl_role= NULL;
char buff[1024];
Protocol *protocol= thd->protocol;
- char *username= NULL, *hostname= NULL, *rolename= NULL;
+ const char *username= NULL, *hostname= NULL, *rolename= NULL, *end;
DBUG_ENTER("mysql_show_grants");
if (!initialized)
@@ -8628,11 +8642,11 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
List<Item> field_list;
if (!username)
- strxmov(buff,"Grants for ",rolename, NullS);
+ end= strxmov(buff,"Grants for ",rolename, NullS);
else
- strxmov(buff,"Grants for ",username,"@",hostname, NullS);
+ end= strxmov(buff,"Grants for ",username,"@",hostname, NullS);
- mysql_show_grants_get_fields(thd, &field_list, buff);
+ mysql_show_grants_get_fields(thd, &field_list, buff, (uint) (end-buff));
if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -8713,9 +8727,9 @@ end:
DBUG_RETURN(error);
}
-static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u,
- const LEX_STRING *h,
- const LEX_STRING *r)
+static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u,
+ const LEX_CSTRING *h,
+ const LEX_CSTRING *r)
{
char buf[1024];
String pair_key(buf, sizeof(buf), &my_charset_bin);
@@ -8736,7 +8750,7 @@ static bool show_role_grants(THD *thd, const char *username,
{
uint counter;
Protocol *protocol= thd->protocol;
- LEX_STRING host= {const_cast<char*>(hostname), strlen(hostname)};
+ LEX_CSTRING host= {const_cast<char*>(hostname), strlen(hostname)};
String grant(buff,sizeof(buff),system_charset_info);
for (counter= 0; counter < acl_entry->role_grants.elements; counter++)
@@ -9547,7 +9561,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
DBUG_RETURN(1);
/* this calls for a role update */
- char *old_key= acl_role->user.str;
+ const char *old_key= acl_role->user.str;
size_t old_key_length= acl_role->user.length;
if (drop)
{
@@ -10895,7 +10909,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
Dummy_error_handler error_handler;
DBUG_ENTER("sp_grant_privileges");
- if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!(combo=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
DBUG_RETURN(TRUE);
combo->user.str= sctx->user;
@@ -11108,8 +11122,8 @@ static int enabled_roles_insert(ACL_USER_BASE *role, void *context_data)
struct APPLICABLE_ROLES_DATA
{
TABLE *table;
- const LEX_STRING host;
- const LEX_STRING user_and_host;
+ const LEX_CSTRING host;
+ const LEX_CSTRING user_and_host;
ACL_USER *user;
};
@@ -11120,9 +11134,9 @@ applicable_roles_insert(ACL_USER_BASE *grantee, ACL_ROLE *role, void *ptr)
CHARSET_INFO *cs= system_charset_info;
TABLE *table= data->table;
bool is_role= grantee != data->user;
- const LEX_STRING *user_and_host= is_role ? &grantee->user
+ const LEX_CSTRING *user_and_host= is_role ? &grantee->user
: &data->user_and_host;
- const LEX_STRING *host= is_role ? &empty_lex_str : &data->host;
+ const LEX_CSTRING *host= is_role ? &empty_clex_str : &data->host;
restore_record(table, s->default_values);
table->field[0]->store(user_and_host->str, user_and_host->length, cs);
@@ -11780,7 +11794,7 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock)
if (lock)
mysql_mutex_lock(&acl_cache->lock);
if (find_acl_role(dup->user.str))
- dup->host= empty_lex_str;
+ dup->host= empty_clex_str;
else
dup->host= host_not_specified;
if (lock)
@@ -11795,7 +11809,7 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock)
struct ACL_internal_schema_registry_entry
{
- const LEX_STRING *m_name;
+ const LEX_CSTRING *m_name;
const ACL_internal_schema_access *m_access;
};
@@ -11816,7 +11830,7 @@ static uint m_registry_array_size= 0;
@param access the schema ACL specific rules
*/
void ACL_internal_schema_registry::register_schema
- (const LEX_STRING *name, const ACL_internal_schema_access *access)
+ (const LEX_CSTRING *name, const ACL_internal_schema_access *access)
{
DBUG_ASSERT(m_registry_array_size < array_elements(registry_array));
@@ -11923,10 +11937,11 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VIO
MYSQL_SERVER_AUTH_INFO auth_info;
ACL_USER *acl_user; ///< a copy, independent from acl_users array
plugin_ref plugin; ///< what plugin we're under
- LEX_STRING db; ///< db name from the handshake packet
+ LEX_CSTRING db; ///< db name from the handshake packet
/** when restarting a plugin this caches the last client reply */
struct {
- char *plugin, *pkt; ///< pointers into NET::buff
+ const char *plugin;
+ char *pkt; ///< pointer into NET::buff
uint pkt_len;
} cached_client_reply;
/** this caches the first plugin packet for restart request on the client */
@@ -12425,7 +12440,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
if (find_mpvio_user(mpvio))
DBUG_RETURN(1);
- char *client_plugin;
+ const char *client_plugin;
if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
{
if (next_field >= end)
@@ -12612,10 +12627,13 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
db_len= safe_strlen(db);
char *next_field;
- char *client_plugin= next_field= passwd + passwd_len + (db ? db_len + 1 : 0);
+ const char *client_plugin= next_field= passwd + passwd_len + (db ? db_len + 1 : 0);
- /* Since 4.1 all database names are stored in utf8 */
- if (thd->copy_with_error(system_charset_info, &mpvio->db,
+ /*
+ Since 4.1 all database names are stored in utf8
+ The cast is ok as copy_with_error will create a new area for db
+ */
+ if (thd->copy_with_error(system_charset_info, (LEX_STRING*) &mpvio->db,
thd->charset(), db, db_len))
return packet_error;
@@ -12642,7 +12660,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
Security_context *sctx= thd->security_ctx;
- my_free(sctx->user);
+ my_free((char*) sctx->user);
if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME))))
return packet_error; /* The error is set by my_strdup(). */
@@ -13003,7 +13021,7 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
}
-static int do_auth_once(THD *thd, const LEX_STRING *auth_plugin_name,
+static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name,
MPVIO_EXT *mpvio)
{
int res= CR_OK, old_status= MPVIO_EXT::FAILURE;
@@ -13085,7 +13103,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
{
int res= CR_OK;
MPVIO_EXT mpvio;
- const LEX_STRING *auth_plugin_name= default_auth_plugin_name;
+ const LEX_CSTRING *auth_plugin_name= default_auth_plugin_name;
enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER
: COM_CONNECT;
DBUG_ENTER("acl_authenticate");
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index daa36f6c32a..f9646649c93 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -182,10 +182,10 @@ enum mysql_db_table_field
extern const TABLE_FIELD_DEF mysql_db_table_def;
extern bool mysql_user_table_is_in_short_password_format;
-extern LEX_STRING host_not_specified;
-extern LEX_STRING current_user;
-extern LEX_STRING current_role;
-extern LEX_STRING current_user_and_current_role;
+extern LEX_CSTRING host_not_specified;
+extern LEX_CSTRING current_user;
+extern LEX_CSTRING current_role;
+extern LEX_CSTRING current_user_and_current_role;
static inline int access_denied_error_code(int passwd_used)
@@ -194,7 +194,6 @@ static inline int access_denied_error_code(int passwd_used)
: ER_ACCESS_DENIED_ERROR;
}
-
/* prototypes */
bool hostname_requires_resolving(const char *hostname);
@@ -204,8 +203,8 @@ void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip,
const char *user, const char *db, my_bool db_is_pattern);
bool acl_authenticate(THD *thd, uint com_change_user_pkt_len);
-bool acl_getroot(Security_context *sctx, char *user, char *host,
- char *ip, char *db);
+bool acl_getroot(Security_context *sctx, const char *user, const char *host,
+ const char *ip, const char *db);
bool acl_check_host(const char *host, const char *ip);
bool check_change_password(THD *thd, LEX_USER *user);
bool change_password(THD *thd, LEX_USER *user);
@@ -243,7 +242,7 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name,
const char *field_name);
void mysql_show_grants_get_fields(THD *thd, List<Item> *fields,
- const char *name);
+ const char *name, size_t length);
bool mysql_show_grants(THD *thd, LEX_USER *user);
bool mysql_show_create_user(THD *thd, LEX_USER *user);
int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond);
@@ -385,7 +384,7 @@ public:
class ACL_internal_schema_registry
{
public:
- static void register_schema(const LEX_STRING *name,
+ static void register_schema(const LEX_CSTRING *name,
const ACL_internal_schema_access *access);
static const ACL_internal_schema_access *lookup(const char *name);
};
@@ -401,8 +400,8 @@ get_cached_table_access(GRANT_INTERNAL_INFO *grant_internal_info,
bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user,
bool with_grant);
-int acl_setrole(THD *thd, char *rolename, ulonglong access);
-int acl_check_setrole(THD *thd, char *rolename, ulonglong *access);
+int acl_setrole(THD *thd, const char *rolename, ulonglong access);
+int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access);
int acl_check_set_default_role(THD *thd, const char *host, const char *user);
int acl_set_default_role(THD *thd, const char *host, const char *user,
const char *rolename);
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 95c2163f043..31933e63b4e 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -189,7 +189,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
if (!mysql_file_stat(key_file_misc, from, &stat_info, MYF(0)))
goto end; // Can't use USE_FRM flag
- my_snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
+ my_snprintf(tmp, sizeof(tmp), "%s-%lx_%llx",
from, current_pid, thd->thread_id);
if (table_list->table)
@@ -341,16 +341,17 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table,
if (lex->alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION ||
!is_view_operator_func)
{
- table->required_type=FRMTYPE_TABLE;
- DBUG_ASSERT(!lex->only_view);
+ table->required_type= TABLE_TYPE_NORMAL;
+ DBUG_ASSERT(lex->table_type != TABLE_TYPE_VIEW);
}
- else if (lex->only_view)
+ else if (lex->table_type == TABLE_TYPE_VIEW)
{
- table->required_type= FRMTYPE_VIEW;
+ table->required_type= lex->table_type;
}
- else if (!lex->only_view && lex->sql_command == SQLCOM_REPAIR)
+ else if ((lex->table_type != TABLE_TYPE_VIEW) &&
+ lex->sql_command == SQLCOM_REPAIR)
{
- table->required_type= FRMTYPE_TABLE;
+ table->required_type= TABLE_TYPE_NORMAL;
}
if (lex->sql_command == SQLCOM_CHECK ||
@@ -393,7 +394,9 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table,
open_and_lock_tables(thd, table, TRUE, 0));
}
+#ifndef DBUG_OFF
dbug_err:
+#endif
thd->prepare_derived_at_open= FALSE;
@@ -488,7 +491,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
for (table= tables; table; table= table->next_local)
{
char table_name[SAFE_NAME_LEN*2+2];
- char* db = table->db;
+ const char *db= table->db;
bool fatal_error=0;
bool open_error;
bool collect_eis= FALSE;
@@ -841,7 +844,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_NO_EIS_FOR_FIELD,
ER_THD(thd, ER_NO_EIS_FOR_FIELD),
- (*field_ptr)->field_name);
+ (*field_ptr)->field_name.str);
}
}
else
@@ -1233,7 +1236,7 @@ err2:
*/
bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
- LEX_STRING *key_cache_name)
+ const LEX_CSTRING *key_cache_name)
{
HA_CHECK_OPT check_opt;
KEY_CACHE *key_cache;
diff --git a/sql/sql_admin.h b/sql/sql_admin.h
index 96594fad0cb..e7f4086540a 100644
--- a/sql/sql_admin.h
+++ b/sql/sql_admin.h
@@ -20,7 +20,7 @@
#define SQL_ADMIN_MSG_TEXT_SIZE (128 * 1024)
bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
- LEX_STRING *key_cache_name);
+ const LEX_CSTRING *key_cache_name);
bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
KEY_CACHE *dst_cache);
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 3592fa3cfbd..0194f26d217 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -50,7 +50,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
}
-bool Alter_info::set_requested_algorithm(const LEX_STRING *str)
+bool Alter_info::set_requested_algorithm(const LEX_CSTRING *str)
{
// To avoid adding new keywords to the grammar, we match strings here.
if (!my_strcasecmp(system_charset_info, str->str, "INPLACE"))
@@ -65,7 +65,7 @@ bool Alter_info::set_requested_algorithm(const LEX_STRING *str)
}
-bool Alter_info::set_requested_lock(const LEX_STRING *str)
+bool Alter_info::set_requested_lock(const LEX_CSTRING *str)
{
// To avoid adding new keywords to the grammar, we match strings here.
if (!my_strcasecmp(system_charset_info, str->str, "NONE"))
@@ -95,10 +95,15 @@ Alter_table_ctx::Alter_table_ctx()
{
}
+/*
+ TODO: new_name_arg changes if lower case table names.
+ Should be copied or converted before call
+*/
Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
uint tables_opened_arg,
- char *new_db_arg, char *new_name_arg)
+ const char *new_db_arg,
+ const char *new_name_arg)
: datetime_field(NULL), error_if_not_empty(false),
tables_opened(tables_opened_arg),
new_db(new_db_arg), new_name(new_name_arg),
@@ -126,13 +131,14 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
if (lower_case_table_names == 1) // Convert new_name/new_alias to lower case
{
- my_casedn_str(files_charset_info, new_name);
+ my_casedn_str(files_charset_info, (char*) new_name);
new_alias= new_name;
}
else if (lower_case_table_names == 2) // Convert new_name to lower case
{
- strmov(new_alias= new_alias_buff, new_name);
- my_casedn_str(files_charset_info, new_name);
+ new_alias= new_alias_buff;
+ strmov(new_alias_buff, new_name);
+ my_casedn_str(files_charset_info, (char*) new_name);
}
else
new_alias= new_name; // LCTN=0 => case sensitive + case preserving
@@ -154,7 +160,7 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list,
new_name= table_name;
}
- my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
+ my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%llx", tmp_file_prefix,
current_pid, thd->thread_id);
/* Safety fix for InnoDB */
if (lower_case_table_names)
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 5668a0f52be..c0232dd7358 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -38,91 +38,65 @@ public:
type of index to be added/dropped.
*/
- // Set for ADD [COLUMN]
- static const uint ALTER_ADD_COLUMN = 1L << 0;
-
- // Set for DROP [COLUMN]
- static const uint ALTER_DROP_COLUMN = 1L << 1;
-
- // Set for CHANGE [COLUMN] | MODIFY [CHANGE]
- // Set by mysql_recreate_table()
- static const uint ALTER_CHANGE_COLUMN = 1L << 2;
-
- // Set for ADD INDEX | ADD KEY | ADD PRIMARY KEY | ADD UNIQUE KEY |
- // ADD UNIQUE INDEX | ALTER ADD [COLUMN]
- static const uint ALTER_ADD_INDEX = 1L << 3;
-
- // Set for DROP PRIMARY KEY | DROP FOREIGN KEY | DROP KEY | DROP INDEX
- static const uint ALTER_DROP_INDEX = 1L << 4;
-
- // Set for RENAME [TO]
- static const uint ALTER_RENAME = 1L << 5;
-
- // Set for ORDER BY
- static const uint ALTER_ORDER = 1L << 6;
-
- // Set for table_options
- static const uint ALTER_OPTIONS = 1L << 7;
-
- // Set for ALTER [COLUMN] ... SET DEFAULT ... | DROP DEFAULT
- static const uint ALTER_CHANGE_COLUMN_DEFAULT = 1L << 8;
-
- // Set for DISABLE KEYS | ENABLE KEYS
- static const uint ALTER_KEYS_ONOFF = 1L << 9;
-
- // Set for FORCE
- // Set for ENGINE(same engine)
- // Set by mysql_recreate_table()
- static const uint ALTER_RECREATE = 1L << 10;
-
- // Set for ADD PARTITION
- static const uint ALTER_ADD_PARTITION = 1L << 11;
-
- // Set for DROP PARTITION
- static const uint ALTER_DROP_PARTITION = 1L << 12;
-
- // Set for COALESCE PARTITION
- static const uint ALTER_COALESCE_PARTITION = 1L << 13;
-
- // Set for REORGANIZE PARTITION ... INTO
- static const uint ALTER_REORGANIZE_PARTITION = 1L << 14;
-
- // Set for partition_options
- static const uint ALTER_PARTITION = 1L << 15;
-
- // Set for LOAD INDEX INTO CACHE ... PARTITION
- // Set for CACHE INDEX ... PARTITION
- static const uint ALTER_ADMIN_PARTITION = 1L << 16;
-
- // Set for REORGANIZE PARTITION
- static const uint ALTER_TABLE_REORG = 1L << 17;
-
- // Set for REBUILD PARTITION
- static const uint ALTER_REBUILD_PARTITION = 1L << 18;
-
- // Set for partitioning operations specifying ALL keyword
- static const uint ALTER_ALL_PARTITION = 1L << 19;
-
- // Set for REMOVE PARTITIONING
- static const uint ALTER_REMOVE_PARTITIONING = 1L << 20;
-
- // Set for ADD FOREIGN KEY
- static const uint ADD_FOREIGN_KEY = 1L << 21;
-
- // Set for DROP FOREIGN KEY
- static const uint DROP_FOREIGN_KEY = 1L << 22;
-
- // Set for EXCHANGE PARITION
- static const uint ALTER_EXCHANGE_PARTITION = 1L << 23;
-
- // Set by Sql_cmd_alter_table_truncate_partition::execute()
- static const uint ALTER_TRUNCATE_PARTITION = 1L << 24;
-
- // Set for ADD [COLUMN] FIRST | AFTER
- static const uint ALTER_COLUMN_ORDER = 1L << 25;
-
- static const uint ALTER_ADD_CHECK_CONSTRAINT = 1L << 27;
- static const uint ALTER_DROP_CHECK_CONSTRAINT = 1L << 28;
+ enum operations_used_flags
+ {
+ // Set for ADD [COLUMN]
+ ALTER_ADD_COLUMN = 1L << 0,
+ // Set for DROP [COLUMN]
+ ALTER_DROP_COLUMN = 1L << 1,
+ // Set for CHANGE [COLUMN] | MODIFY [CHANGE] & mysql_recreate_table
+ ALTER_CHANGE_COLUMN = 1L << 2,
+ // Set for ADD INDEX | ADD KEY | ADD PRIMARY KEY | ADD UNIQUE KEY |
+ // ADD UNIQUE INDEX | ALTER ADD [COLUMN]
+ ALTER_ADD_INDEX = 1L << 3,
+ // Set for DROP PRIMARY KEY | DROP FOREIGN KEY | DROP KEY | DROP INDEX
+ ALTER_DROP_INDEX = 1L << 4,
+ // Set for RENAME [TO]
+ ALTER_RENAME = 1L << 5,
+ // Set for ORDER BY
+ ALTER_ORDER = 1L << 6,
+ // Set for table_options
+ ALTER_OPTIONS = 1L << 7,
+ // Set for ALTER [COLUMN] ... SET DEFAULT ... | DROP DEFAULT
+ ALTER_CHANGE_COLUMN_DEFAULT = 1L << 8,
+ // Set for DISABLE KEYS | ENABLE KEYS
+ ALTER_KEYS_ONOFF = 1L << 9,
+ // Set for FORCE, ENGINE(same engine), by mysql_recreate_table()
+ ALTER_RECREATE = 1L << 10,
+ // Set for ADD PARTITION
+ ALTER_ADD_PARTITION = 1L << 11,
+ // Set for DROP PARTITION
+ ALTER_DROP_PARTITION = 1L << 12,
+ // Set for COALESCE PARTITION
+ ALTER_COALESCE_PARTITION = 1L << 13,
+ // Set for REORGANIZE PARTITION ... INTO
+ ALTER_REORGANIZE_PARTITION = 1L << 14,
+ // Set for partition_options
+ ALTER_PARTITION = 1L << 15,
+ // Set for LOAD INDEX INTO CACHE ... PARTITION
+ // Set for CACHE INDEX ... PARTITION
+ ALTER_ADMIN_PARTITION = 1L << 16,
+ // Set for REORGANIZE PARTITION
+ ALTER_TABLE_REORG = 1L << 17,
+ // Set for REBUILD PARTITION
+ ALTER_REBUILD_PARTITION = 1L << 18,
+ // Set for partitioning operations specifying ALL keyword
+ ALTER_ALL_PARTITION = 1L << 19,
+ // Set for REMOVE PARTITIONING
+ ALTER_REMOVE_PARTITIONING = 1L << 20,
+ // Set for ADD FOREIGN KEY
+ ADD_FOREIGN_KEY = 1L << 21,
+ // Set for DROP FOREIGN KEY
+ DROP_FOREIGN_KEY = 1L << 22,
+ // Set for EXCHANGE PARITION
+ ALTER_EXCHANGE_PARTITION = 1L << 23,
+ // Set by Sql_cmd_alter_table_truncate_partition::execute()
+ ALTER_TRUNCATE_PARTITION = 1L << 24,
+ // Set for ADD [COLUMN] FIRST | AFTER
+ ALTER_COLUMN_ORDER = 1L << 25,
+ ALTER_ADD_CHECK_CONSTRAINT = 1L << 27,
+ ALTER_DROP_CHECK_CONSTRAINT = 1L << 28
+ };
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
@@ -172,14 +146,17 @@ public:
// List of columns, used by both CREATE and ALTER TABLE.
List<Create_field> create_list;
- static const uint CHECK_CONSTRAINT_IF_NOT_EXISTS= 1;
+ enum flags_bits
+ {
+ CHECK_CONSTRAINT_IF_NOT_EXISTS= 1
+ };
List<Virtual_column_info> check_constraint_list;
// Type of ALTER TABLE operation.
uint flags;
// Enable or disable keys.
enum_enable_or_disable keys_onoff;
// List of partitions.
- List<char> partition_names;
+ List<const char> partition_names;
// Number of partitions.
uint num_parts;
// Type of ALTER TABLE algorithm.
@@ -239,7 +216,7 @@ public:
@retval false Supported value found, state updated
@retval true Not supported value, no changes made
*/
- bool set_requested_algorithm(const LEX_STRING *str);
+ bool set_requested_algorithm(const LEX_CSTRING *str);
/**
@@ -252,7 +229,7 @@ public:
@retval true Not supported value, no changes made
*/
- bool set_requested_lock(const LEX_STRING *str);
+ bool set_requested_lock(const LEX_CSTRING *str);
private:
Alter_info &operator=(const Alter_info &rhs); // not implemented
@@ -267,7 +244,7 @@ public:
Alter_table_ctx();
Alter_table_ctx(THD *thd, TABLE_LIST *table_list, uint tables_opened_arg,
- char *new_db_arg, char *new_name_arg);
+ const char *new_db_arg, const char *new_name_arg);
/**
@return true if the table is moved to another database, false otherwise.
@@ -329,12 +306,12 @@ public:
Create_field *datetime_field;
bool error_if_not_empty;
uint tables_opened;
- char *db;
- char *table_name;
- char *alias;
- char *new_db;
- char *new_name;
- char *new_alias;
+ const char *db;
+ const char *table_name;
+ const char *alias;
+ const char *new_db;
+ const char *new_name;
+ const char *new_alias;
char tmp_name[80];
/**
Indicates that if a row is deleted during copying of data from old version
@@ -408,6 +385,29 @@ public:
/**
+ Sql_cmd_alter_sequence represents the ALTER SEQUENCE statement.
+*/
+class Sql_cmd_alter_sequence : public Sql_cmd
+{
+public:
+ /**
+ Constructor, used to represent a ALTER TABLE statement.
+ */
+ Sql_cmd_alter_sequence()
+ {}
+
+ ~Sql_cmd_alter_sequence()
+ {}
+
+ enum_sql_command sql_command_code() const
+ {
+ return SQLCOM_ALTER_SEQUENCE;
+ }
+ bool execute(THD *thd);
+};
+
+
+/**
Sql_cmd_alter_table_tablespace represents ALTER TABLE
IMPORT/DISCARD TABLESPACE statements.
*/
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 91a80c552cb..d6af0410ad2 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -72,7 +72,7 @@ Procedure *
proc_analyse_init(THD *thd, ORDER *param, select_result *result,
List<Item> &field_list)
{
- char *proc_name = (*param->item)->name;
+ const char *proc_name = (*param->item)->name.str;
analyse *pc = new analyse(result);
field_info **f_info;
DBUG_ENTER("proc_analyse_init");
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 903e90d73f0..7041e22075b 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -502,7 +502,7 @@ err_with_reopen:
struct close_cached_connection_tables_arg
{
THD *thd;
- LEX_STRING *connection;
+ LEX_CSTRING *connection;
TABLE_LIST *tables;
};
@@ -547,7 +547,7 @@ end:
}
-bool close_cached_connection_tables(THD *thd, LEX_STRING *connection)
+bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
{
close_cached_connection_tables_arg argument;
DBUG_ENTER("close_cached_connections");
@@ -1481,7 +1481,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
TABLE *table;
const char *key;
uint key_length;
- char *alias= table_list->alias;
+ const char *alias= table_list->alias;
uint flags= ot_ctx->get_flags();
MDL_ticket *mdl_ticket;
TABLE_SHARE *share;
@@ -1783,7 +1783,11 @@ retry_share:
my_error(ER_WRONG_MRG_TABLE, MYF(0));
goto err_lock;
}
-
+ if (table_list->sequence)
+ {
+ my_error(ER_NOT_SEQUENCE, MYF(0), table_list->db, table_list->alias);
+ goto err_lock;
+ }
/*
This table is a view. Validate its metadata version: in particular,
that it was a view when the statement was prepared.
@@ -1934,6 +1938,11 @@ retry_share:
DBUG_RETURN(true);
}
#endif
+ if (table_list->sequence && table->s->table_type != TABLE_TYPE_SEQUENCE)
+ {
+ my_error(ER_NOT_SEQUENCE, MYF(0), table_list->db, table_list->alias);
+ DBUG_RETURN(true);
+ }
table->init(thd, table_list);
@@ -3650,8 +3659,9 @@ lock_table_names(THD *thd, const DDL_options_st &options,
DBUG_RETURN(FALSE);
/* Check if CREATE TABLE without REPLACE was used */
- create_table= thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
- !options.or_replace();
+ create_table= ((thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
+ thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE) &&
+ !options.or_replace());
if (!(flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK))
{
@@ -4168,8 +4178,9 @@ handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
@note this can be changed to use a hash, instead of scanning the linked
list, if the performance of this function will ever become an issue
*/
-static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_STRING *db,
- LEX_STRING *table, thr_lock_type lock_type)
+static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db,
+ LEX_CSTRING *table,
+ thr_lock_type lock_type)
{
for (; tl; tl= tl->next_global )
{
@@ -4519,7 +4530,7 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
/* Set requested lock type. */
table_l->lock_type= lock_type;
/* Allow to open real tables only. */
- table_l->required_type= FRMTYPE_TABLE;
+ table_l->required_type= TABLE_TYPE_NORMAL;
/* Open the table. */
if (open_and_lock_tables(thd, table_l, FALSE, flags,
@@ -4575,7 +4586,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
THD_STAGE_INFO(thd, stage_opening_tables);
thd->current_tablenr= 0;
/* open_ltable can be used only for BASIC TABLEs */
- table_list->required_type= FRMTYPE_TABLE;
+ table_list->required_type= TABLE_TYPE_NORMAL;
/* This function can't properly handle requests for such metadata locks. */
DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
@@ -4764,6 +4775,51 @@ end:
}
+/**
+ Open a table to read its structure, e.g. for:
+ - SHOW FIELDS
+ - delayed SP variable data type definition: DECLARE a t1.a%TYPE
+
+ The flag MYSQL_OPEN_GET_NEW_TABLE is passed to make %TYPE work
+ in stored functions, as during a stored function call
+ (e.g. in a SELECT query) the tables referenced in %TYPE can already be locked,
+ and attempt to open it again would return an error in open_table().
+
+ The flag MYSQL_OPEN_GET_NEW_TABLE is not really needed for
+ SHOW FIELDS or for a "CALL sp()" statement, but it's not harmful,
+ so let's pass it unconditionally.
+*/
+
+bool open_tables_only_view_structure(THD *thd, TABLE_LIST *table_list,
+ bool can_deadlock)
+{
+ DBUG_ENTER("open_tables_only_view_structure");
+ /*
+ Let us set fake sql_command so views won't try to merge
+ themselves into main statement. If we don't do this,
+ SELECT * from information_schema.xxxx will cause problems.
+ SQLCOM_SHOW_FIELDS is used because it satisfies
+ 'LEX::only_view_structure()'.
+ */
+ enum_sql_command save_sql_command= thd->lex->sql_command;
+ thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
+ bool rc= (thd->open_temporary_tables(table_list) ||
+ open_normal_and_derived_tables(thd, table_list,
+ (MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
+ MYSQL_OPEN_GET_NEW_TABLE |
+ (can_deadlock ?
+ MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)),
+ DT_INIT | DT_PREPARE | DT_CREATE));
+ /*
+ Restore old value of sql_command back as it is being looked at in
+ process_table() function.
+ */
+ thd->lex->sql_command= save_sql_command;
+ DBUG_RETURN(rc);
+}
+
+
/*
Mark all real tables in the list as free for reuse.
@@ -5196,7 +5252,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
for (; !field_it.end_of_fields(); field_it.next())
{
- if (!my_strcasecmp(system_charset_info, field_it.name(), name))
+ if (!my_strcasecmp(system_charset_info, field_it.name()->str, name))
{
// in PS use own arena or data will be freed after prepare
if (register_tree_change &&
@@ -5218,27 +5274,10 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
*ref != NULL means that *ref contains the item that we need to
replace. If the item was aliased by the user, set the alias to
the replacing item.
- We need to set alias on both ref itself and on ref real item.
*/
if (*ref && !(*ref)->is_autogenerated_name)
- {
- if (register_tree_change)
- {
- item->set_name_for_rollback(thd, (*ref)->name,
- (*ref)->name_length,
- system_charset_info);
- item->real_item()->set_name_for_rollback(thd, (*ref)->name,
- (*ref)->name_length,
- system_charset_info);
- }
- else
- {
- item->set_name(thd, (*ref)->name, (*ref)->name_length,
- system_charset_info);
- item->real_item()->set_name(thd, (*ref)->name, (*ref)->name_length,
- system_charset_info);
- }
- }
+ item->set_name(thd, (*ref)->name.str, (*ref)->name.length,
+ system_charset_info);
if (register_tree_change)
thd->change_item_tree(ref, item);
else
@@ -5298,7 +5337,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
for (nj_col= NULL, curr_nj_col= field_it++; curr_nj_col;
curr_nj_col= field_it++)
{
- if (!my_strcasecmp(system_charset_info, curr_nj_col->name(), name))
+ if (!my_strcasecmp(system_charset_info, curr_nj_col->name()->str, name))
{
if (nj_col)
{
@@ -5325,15 +5364,10 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
*ref != NULL means that *ref contains the item that we need to
replace. If the item was aliased by the user, set the alias to
the replacing item.
- We need to set alias on both ref itself and on ref real item.
*/
if (*ref && !(*ref)->is_autogenerated_name)
- {
- item->set_name(thd, (*ref)->name, (*ref)->name_length,
+ item->set_name(thd, (*ref)->name.str, (*ref)->name.length,
system_charset_info);
- item->real_item()->set_name(thd, (*ref)->name, (*ref)->name_length,
- system_charset_info);
- }
if (register_tree_change && arena)
thd->restore_active_arena(arena, &backup);
@@ -5370,7 +5404,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
nj_col->table_field->fix_fields(thd, &ref))
{
DBUG_PRINT("info", ("column '%s' was dropped by the concurrent connection",
- nj_col->table_field->name));
+ nj_col->table_field->name.str));
DBUG_RETURN(NULL);
}
DBUG_ASSERT(ref == 0); // Should not have changed
@@ -5418,7 +5452,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
/* We assume here that table->field < NO_CACHED_FIELD_INDEX = UINT_MAX */
if (cached_field_index < table->s->fields &&
!my_strcasecmp(system_charset_info,
- table->field[cached_field_index]->field_name, name))
+ table->field[cached_field_index]->field_name.str, name))
field_ptr= table->field + cached_field_index;
else if (table->s->name_hash.records)
{
@@ -5438,7 +5472,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
if (!(field_ptr= table->field))
DBUG_RETURN((Field *)0);
for (; *field_ptr; ++field_ptr)
- if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name))
+ if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name.str,
+ name))
break;
}
@@ -5558,6 +5593,13 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
strcmp(db_name, table_list->db)))))
DBUG_RETURN(0);
+ /*
+ Don't allow usage of fields in sequence table that is opened as part of
+ NEXT VALUE for sequence_name
+ */
+ if (table_list->sequence)
+ DBUG_RETURN(0);
+
*actual_table= NULL;
if (table_list->field_translation)
@@ -5694,7 +5736,8 @@ Field *find_field_in_table_sef(TABLE *table, const char *name)
if (!(field_ptr= table->field))
return (Field *)0;
for (; *field_ptr; ++field_ptr)
- if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name))
+ if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name.str,
+ name))
break;
}
if (field_ptr)
@@ -5747,8 +5790,8 @@ find_field_in_tables(THD *thd, Item_ident *item,
Field *found=0;
const char *db= item->db_name;
const char *table_name= item->table_name;
- const char *name= item->field_name;
- uint length=(uint) strlen(name);
+ const char *name= item->field_name.str;
+ uint length= item->field_name.length;
char name_buff[SAFE_NAME_LEN+1];
TABLE_LIST *cur_table= first_table;
TABLE_LIST *actual_table;
@@ -5795,7 +5838,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
#endif
}
else
- found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
+ found= find_field_in_table_ref(thd, table_ref, name, length, item->name.str,
NULL, NULL, ref, check_privileges,
TRUE, &(item->cached_field_index),
register_tree_change,
@@ -5863,7 +5906,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
cur_table= cur_table->next_name_resolution_table)
{
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length,
- item->name, db, table_name, ref,
+ item->name.str, db, table_name, ref,
(thd->lex->sql_command ==
SQLCOM_SHOW_FIELDS)
? false : check_privileges,
@@ -5880,7 +5923,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
thd->clear_error();
cur_field= find_field_in_table_ref(thd, cur_table, name, length,
- item->name, db, table_name, ref,
+ item->name.str, db, table_name, ref,
false,
allow_rowid,
&(item->cached_field_index),
@@ -5889,7 +5932,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
if (cur_field)
{
Field *nf=new Field_null(NULL,0,Field::NONE,
- cur_field->field_name,
+ &cur_field->field_name,
&my_charset_bin);
nf->init(cur_table->table);
cur_field= nf;
@@ -6005,7 +6048,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
uint n_items= limit == 0 ? items.elements : limit;
Item **found=0, **found_unaliased= 0, *item;
const char *db_name=0;
- const char *field_name=0;
+ const LEX_CSTRING *field_name= 0;
const char *table_name=0;
bool found_unaliased_non_uniq= 0;
/*
@@ -6021,7 +6064,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
find->type() == Item::REF_ITEM);
if (is_ref_by_name)
{
- field_name= ((Item_ident*) find)->field_name;
+ field_name= &((Item_ident*) find)->field_name;
table_name= ((Item_ident*) find)->table_name;
db_name= ((Item_ident*) find)->db_name;
}
@@ -6029,7 +6072,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
for (uint i= 0; i < n_items; i++)
{
item= li++;
- if (field_name &&
+ if (field_name && field_name->str &&
(item->real_item()->type() == Item::FIELD_ITEM ||
((item->type() == Item::REF_ITEM) &&
(((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF))))
@@ -6042,7 +6085,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
(if this field created from expression argument of group_concat()),
=> we have to check presence of name before compare
*/
- if (!item_field->name)
+ if (!item_field->name.str)
continue;
if (table_name)
@@ -6063,9 +6106,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
item_field->field_name and item_field->table_name can be 0x0 if
item is not fix_field()'ed yet.
*/
- if (item_field->field_name && item_field->table_name &&
- !my_strcasecmp(system_charset_info, item_field->field_name,
- field_name) &&
+ if (item_field->field_name.str && item_field->table_name &&
+ !my_strcasecmp(system_charset_info, item_field->field_name.str,
+ field_name->str) &&
!my_strcasecmp(table_alias_charset, item_field->table_name,
table_name) &&
(!db_name || (item_field->db_name &&
@@ -6095,10 +6138,10 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
else
{
int fname_cmp= my_strcasecmp(system_charset_info,
- item_field->field_name,
- field_name);
+ item_field->field_name.str,
+ field_name->str);
if (!my_strcasecmp(system_charset_info,
- item_field->name,field_name))
+ item_field->name.str,field_name->str))
{
/*
If table name was not given we should scan through aliases
@@ -6142,8 +6185,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
}
else if (!table_name)
{
- if (is_ref_by_name && find->name && item->name &&
- !my_strcasecmp(system_charset_info,item->name,find->name))
+ if (is_ref_by_name && find->name.str && item->name.str &&
+ find->name.length == item->name.length &&
+ !my_strcasecmp(system_charset_info,item->name.str, find->name.str))
{
found= li.ref();
*counter= i;
@@ -6317,17 +6361,17 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next())
{
bool found= FALSE;
- const char *field_name_1;
+ const LEX_CSTRING *field_name_1;
/* true if field_name_1 is a member of using_fields */
bool is_using_column_1;
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, leaf_1)))
goto err;
field_name_1= nj_col_1->name();
is_using_column_1= using_fields &&
- test_if_string_in_list(field_name_1, using_fields);
+ test_if_string_in_list(field_name_1->str, using_fields);
DBUG_PRINT ("info", ("field_name_1=%s.%s",
nj_col_1->table_name() ? nj_col_1->table_name() : "",
- field_name_1));
+ field_name_1->str));
/*
Find a field with the same name in table_ref_2.
@@ -6340,14 +6384,14 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next())
{
Natural_join_column *cur_nj_col_2;
- const char *cur_field_name_2;
+ const LEX_CSTRING *cur_field_name_2;
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, leaf_2)))
goto err;
cur_field_name_2= cur_nj_col_2->name();
DBUG_PRINT ("info", ("cur_field_name_2=%s.%s",
cur_nj_col_2->table_name() ?
cur_nj_col_2->table_name() : "",
- cur_field_name_2));
+ cur_field_name_2->str));
/*
Compare the two columns and check for duplicate common fields.
@@ -6360,13 +6404,14 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
here. These columns must be checked only on unqualified reference
by name (e.g. in SELECT list).
*/
- if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2))
+ if (!my_strcasecmp(system_charset_info, field_name_1->str,
+ cur_field_name_2->str))
{
DBUG_PRINT ("info", ("match c1.is_common=%d", nj_col_1->is_common));
if (cur_nj_col_2->is_common ||
(found && (!using_fields || is_using_column_1)))
{
- my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1->str, thd->where);
goto err;
}
nj_col_2= cur_nj_col_2;
@@ -6457,10 +6502,10 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
DBUG_PRINT ("info", ("%s.%s and %s.%s are common",
nj_col_1->table_name() ?
nj_col_1->table_name() : "",
- nj_col_1->name(),
+ nj_col_1->name()->str,
nj_col_2->table_name() ?
nj_col_2->table_name() : "",
- nj_col_2->name()));
+ nj_col_2->name()->str));
if (field_1)
{
@@ -6598,7 +6643,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
goto err;
}
if (!my_strcasecmp(system_charset_info,
- common_field->name(), using_field_name_ptr))
+ common_field->name()->str, using_field_name_ptr))
break; // Found match
}
}
@@ -6925,8 +6970,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
while (wild_num && (item= it++))
{
if (item->type() == Item::FIELD_ITEM &&
- ((Item_field*) item)->field_name &&
- ((Item_field*) item)->field_name[0] == '*' &&
+ ((Item_field*) item)->field_name.str == star_clex_str.str &&
!((Item_field*) item)->field)
{
uint elem= fields.elements;
@@ -7547,7 +7591,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
!(fld->have_privileges=
(get_column_grant(thd, field_iterator.grant(),
field_iterator.get_db_name(),
- field_table_name, fld->field_name) &
+ field_table_name, fld->field_name.str) &
VIEW_ANY_ACL)))
{
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY",
@@ -7876,7 +7920,7 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
fld= (Item_field*)f++;
if (!(field= fld->field_for_view_update()))
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name.str);
goto err;
}
DBUG_ASSERT(field->field->table == table_arg);
@@ -7888,7 +7932,7 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
{
if (!(field= fld->field_for_view_update()))
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name.str);
goto err;
}
value=v++;
@@ -7906,7 +7950,7 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
- rfield->field_name, table->s->table_name.str);
+ rfield->field_name.str, table->s->table_name.str);
}
if (rfield->stored_in_db() &&
(value->save_in_field(rfield, 0)) < 0 && !ignore_errors)
@@ -8151,7 +8195,7 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
- field->field_name, table->s->table_name.str);
+ field->field_name.str, table->s->table_name.str);
}
}
@@ -8415,7 +8459,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
}
-bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
+bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b)
{
return a->length == b->length && !strncmp(a->str, b->str, a->length);
}
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 374ac56c3d8..7a8d27c9147 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -254,12 +254,14 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
Prelocking_strategy *prelocking_strategy);
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
uint dt_phases);
+bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables,
+ bool can_deadlock);
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
void close_thread_table(THD *thd, TABLE **table_ptr);
TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
bool check_alias);
-bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
+bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b);
class Open_tables_backup;
/* Functions to work with system tables. */
@@ -277,7 +279,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup);
bool close_cached_tables(THD *thd, TABLE_LIST *tables,
bool wait_for_refresh, ulong timeout);
-bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
+bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connect_string);
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
ha_extra_function extra,
TABLE *skip_table);
diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in
index a40a064dc4b..6a491a3e7bb 100644
--- a/sql/sql_builtin.cc.in
+++ b/sql/sql_builtin.cc.in
@@ -11,7 +11,13 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ Note that sql_builtin.cc is automatically built by sql_bultin.cc.in
+ and cmake/plugin.cmake
+*/
#include <my_global.h>
#include <mysql/plugin.h>
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 18a75dd9024..89afef4eaf7 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -2330,7 +2330,7 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
Remove all cached queries that uses the given database.
*/
-void Query_cache::invalidate(THD *thd, char *db)
+void Query_cache::invalidate(THD *thd, const char *db)
{
DBUG_ENTER("Query_cache::invalidate (db)");
if (is_disabled())
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 945de307ffb..21f9c66dc4f 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -78,7 +78,7 @@ struct Query_cache_tls;
struct LEX;
class THD;
-typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
+typedef my_bool (*qc_engine_callback)(THD *thd, const char *table_key,
uint key_length,
ulonglong *engine_data);
@@ -482,7 +482,7 @@ protected:
my_bool using_transactions);
/* Remove all queries that uses any of the tables in following database */
- void invalidate(THD *thd, char *db);
+ void invalidate(THD *thd, const char *db);
/* Remove all queries that uses any of the listed following table */
void invalidate_by_MyISAM_filename(const char *filename);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index e07b03f7bb1..c33f01d0084 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -55,6 +55,7 @@
#include <mysys_err.h>
#include <limits.h>
+#include "sp_head.h"
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "transaction.h"
@@ -100,6 +101,23 @@ extern "C" void free_user_var(user_var_entry *entry)
my_free(entry);
}
+/* Functions for last-value-from-sequence hash */
+
+extern "C" uchar *get_sequence_last_key(SEQUENCE_LAST_VALUE *entry,
+ size_t *length,
+ my_bool not_used
+ __attribute__((unused)))
+{
+ *length= entry->length;
+ return (uchar*) entry->key;
+}
+
+extern "C" void free_sequence_last(SEQUENCE_LAST_VALUE *entry)
+{
+ delete entry;
+}
+
+
bool Key_part_spec::operator==(const Key_part_spec& other) const
{
return length == other.length &&
@@ -233,10 +251,10 @@ bool Foreign_key::validate(List<Create_field> &table_fields)
while ((sql_field= it++) &&
my_strcasecmp(system_charset_info,
column->field_name.str,
- sql_field->field_name)) {}
+ sql_field->field_name.str)) {}
if (!sql_field)
{
- my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
@@ -548,8 +566,8 @@ char *thd_get_error_context_description(THD *thd, char *buffer,
const char *proc_info= thd->proc_info;
len= my_snprintf(header, sizeof(header),
- "MySQL thread id %lu, OS thread handle 0x%lx, query id %lu",
- thd->thread_id, (ulong) thd->real_id, (ulong) thd->query_id);
+ "MySQL thread id %lu, OS thread handle %p, query id %lu",
+ (ulong) thd->thread_id, (void*) thd->real_id, (ulong) thd->query_id);
str.length(0);
str.append(header, len);
@@ -879,6 +897,9 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(my_hash_get_key) get_var_key,
(my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC);
+ my_hash_init(&sequences, system_charset_info, SEQUENCES_HASH_SIZE, 0, 0,
+ (my_hash_get_key) get_sequence_last_key,
+ (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC);
sp_proc_cache= NULL;
sp_func_cache= NULL;
@@ -918,8 +939,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
}
m_binlog_invoker= INVOKER_NONE;
- memset(&invoker_user, 0, sizeof(invoker_user));
- memset(&invoker_host, 0, sizeof(invoker_host));
+ invoker.init();
prepare_derived_at_open= FALSE;
create_tmp_table_for_derived= FALSE;
save_prep_leaf_list= FALSE;
@@ -1066,9 +1086,10 @@ void THD::raise_note_printf(uint sql_errno, ...)
}
Sql_condition* THD::raise_condition(uint sql_errno,
- const char* sqlstate,
- Sql_condition::enum_warning_level level,
- const char* msg)
+ const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const Sql_user_condition_identity &ucid,
+ const char* msg)
{
Diagnostics_area *da= get_stmt_da();
Sql_condition *cond= NULL;
@@ -1127,7 +1148,7 @@ Sql_condition* THD::raise_condition(uint sql_errno,
if (!da->is_error())
{
set_row_count_func(-1);
- da->set_error_status(sql_errno, msg, sqlstate, cond);
+ da->set_error_status(sql_errno, msg, sqlstate, ucid, cond);
}
}
@@ -1141,7 +1162,7 @@ Sql_condition* THD::raise_condition(uint sql_errno,
if (!(is_fatal_error && (sql_errno == EE_OUTOFMEMORY ||
sql_errno == ER_OUTOFMEMORY)))
{
- cond= da->push_warning(this, sql_errno, sqlstate, level, msg);
+ cond= da->push_warning(this, sql_errno, sqlstate, level, ucid, msg);
}
DBUG_RETURN(cond);
}
@@ -1171,11 +1192,11 @@ char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size)
}
extern "C"
-LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
+LEX_CSTRING *thd_make_lex_string(THD *thd, LEX_CSTRING *lex_str,
const char *str, unsigned int size,
int allocate_lex_string)
{
- return allocate_lex_string ? thd->make_lex_string(str, size)
+ return allocate_lex_string ? thd->make_clex_string(str, size)
: thd->make_lex_string(lex_str, str, size);
}
@@ -1224,6 +1245,17 @@ extern "C" my_thread_id next_thread_id_noinline()
}
#endif
+
+const Type_handler *THD::type_handler_for_date() const
+{
+ if (!(variables.sql_mode & MODE_ORACLE))
+ return &type_handler_newdate;
+ if (opt_mysql56_temporal_format)
+ return &type_handler_datetime2;
+ return &type_handler_datetime;
+}
+
+
/*
Init common variables that has to be reset on start and on change_user
*/
@@ -1241,7 +1273,7 @@ void THD::init(void)
variables.pseudo_thread_id= thread_id;
variables.default_master_connection.str= default_master_connection_buff;
- ::strmake(variables.default_master_connection.str,
+ ::strmake(default_master_connection_buff,
global_system_variables.default_master_connection.str,
variables.default_master_connection.length);
@@ -1324,7 +1356,17 @@ void THD::init(void)
DBUG_VOID_RETURN;
}
-
+
+bool THD::restore_from_local_lex_to_old_lex(LEX *oldlex)
+{
+ DBUG_ASSERT(lex->sphead);
+ if (lex->sphead->merge_lex(this, oldlex, lex))
+ return true;
+ lex= oldlex;
+ return false;
+}
+
+
/* Updates some status variables to be used by update_global_user_stats */
void THD::update_stats(void)
@@ -1418,6 +1460,9 @@ void THD::change_user(void)
my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(my_hash_get_key) get_var_key,
(my_hash_free_key) free_user_var, 0);
+ my_hash_init(&sequences, system_charset_info, SEQUENCES_HASH_SIZE, 0, 0,
+ (my_hash_get_key) get_sequence_last_key,
+ (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC);
sp_cache_clear(&sp_proc_cache);
sp_cache_clear(&sp_func_cache);
}
@@ -1474,6 +1519,7 @@ void THD::cleanup(void)
#endif /* defined(ENABLED_DEBUG_SYNC) */
my_hash_free(&user_vars);
+ my_hash_free(&sequences);
sp_cache_clear(&sp_proc_cache);
sp_cache_clear(&sp_func_cache);
auto_inc_intervals_forced.empty();
@@ -2318,6 +2364,26 @@ bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
}
+Item_string *THD::make_string_literal(const char *str, size_t length,
+ uint repertoire)
+{
+ if (!charset_is_collation_connection &&
+ (repertoire != MY_REPERTOIRE_ASCII ||
+ !my_charset_is_ascii_based(variables.collation_connection)))
+ {
+ LEX_STRING to;
+ if (convert_string(&to, variables.collation_connection,
+ str, length, variables.character_set_client))
+ return NULL;
+ str= to.str;
+ length= to.length;
+ }
+ return new (mem_root) Item_string(this, str, length,
+ variables.collation_connection,
+ DERIVATION_COERCIBLE, repertoire);
+}
+
+
/*
Update some cache variables when character set changes
*/
@@ -2671,7 +2737,7 @@ static String default_field_term("\t",default_charset_info);
static String default_enclosed_and_line_start("", default_charset_info);
static String default_xml_row_term("<row>", default_charset_info);
-sql_exchange::sql_exchange(char *name, bool flag,
+sql_exchange::sql_exchange(const char *name, bool flag,
enum enum_filetype filetype_arg)
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
{
@@ -3066,7 +3132,7 @@ int select_export::send_data(List<Item> &items)
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER_THD(thd, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", printable_buff,
- item->name, static_cast<long>(row_count));
+ item->name.str, static_cast<long>(row_count));
}
else if (copier.source_end_pos() < res->ptr() + res->length())
{
@@ -3349,7 +3415,7 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
{
if (!cache)
{
- cache= Item_cache::get_cache(thd, val_item);
+ cache= val_item->get_cache(thd);
switch (val_item->result_type()) {
case REAL_RESULT:
op= &select_max_min_finder_subselect::cmp_real;
@@ -3471,15 +3537,29 @@ int select_exists_subselect::send_data(List<Item> &items)
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
+ my_var_sp *mvsp;
unit= u;
-
- if (var_list.elements != list.elements)
+ m_var_sp_row= NULL;
+
+ if (var_list.elements == 1 &&
+ (mvsp= var_list.head()->get_my_var_sp()) &&
+ mvsp->type_handler() == &type_handler_row)
{
- my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
- ER_THD(thd, ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
- return 1;
- }
- return 0;
+ // SELECT INTO row_type_sp_variable
+ if (thd->spcont->get_item(mvsp->offset)->cols() != list.elements)
+ goto error;
+ m_var_sp_row= mvsp;
+ return 0;
+ }
+
+ // SELECT INTO variable list
+ if (var_list.elements == list.elements)
+ return 0;
+
+error:
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER_THD(thd, ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
+ return 1;
}
@@ -3805,7 +3885,7 @@ Statement_map::~Statement_map()
bool my_var_user::set(THD *thd, Item *item)
{
- Item_func_set_user_var *suv= new (thd->mem_root) Item_func_set_user_var(thd, name, item);
+ Item_func_set_user_var *suv= new (thd->mem_root) Item_func_set_user_var(thd, &name, item);
suv->save_item_result(item);
return suv->fix_fields(thd, 0) || suv->update();
}
@@ -3815,12 +3895,30 @@ bool my_var_sp::set(THD *thd, Item *item)
return thd->spcont->set_variable(thd, offset, &item);
}
-int select_dumpvar::send_data(List<Item> &items)
+bool my_var_sp_row_field::set(THD *thd, Item *item)
+{
+ return thd->spcont->set_variable_row_field(thd, offset, m_field_offset, &item);
+}
+
+
+bool select_dumpvar::send_data_to_var_list(List<Item> &items)
{
+ DBUG_ENTER("select_dumpvar::send_data_to_var_list");
List_iterator_fast<my_var> var_li(var_list);
List_iterator<Item> it(items);
Item *item;
my_var *mv;
+ while ((mv= var_li++) && (item= it++))
+ {
+ if (mv->set(thd, item))
+ DBUG_RETURN(true);
+ }
+ DBUG_RETURN(false);
+}
+
+
+int select_dumpvar::send_data(List<Item> &items)
+{
DBUG_ENTER("select_dumpvar::send_data");
if (unit->offset_limit_cnt)
@@ -3833,11 +3931,11 @@ int select_dumpvar::send_data(List<Item> &items)
my_message(ER_TOO_MANY_ROWS, ER_THD(thd, ER_TOO_MANY_ROWS), MYF(0));
DBUG_RETURN(1);
}
- while ((mv= var_li++) && (item= it++))
- {
- if (mv->set(thd, item))
- DBUG_RETURN(1);
- }
+ if (m_var_sp_row ?
+ thd->spcont->set_variable_row(thd, m_var_sp_row->offset, items) :
+ send_data_to_var_list(items))
+ DBUG_RETURN(1);
+
DBUG_RETURN(thd->is_error());
}
@@ -3867,7 +3965,8 @@ create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long,
bool create_table,
- bool keep_row_order)
+ bool keep_row_order,
+ uint hidden)
{
DBUG_ASSERT(table == 0);
tmp_table_param.field_count= column_types->elements;
@@ -3902,12 +4001,12 @@ void select_materialize_with_stats::reset()
void select_materialize_with_stats::cleanup()
{
reset();
- select_union::cleanup();
+ select_unit::cleanup();
}
/**
- Override select_union::send_data to analyze each row for NULLs and to
+ Override select_unit::send_data to analyze each row for NULLs and to
update null_statistics before sending data to the client.
@return TRUE if fatal error when sending data to the client
@@ -3922,7 +4021,7 @@ int select_materialize_with_stats::send_data(List<Item> &items)
uint nulls_in_row= 0;
int res;
- if ((res= select_union::send_data(items)))
+ if ((res= select_unit::send_data(items)))
return res;
if (table->null_catch_flags & REJECT_ROW_DUE_TO_NULL_FIELDS)
{
@@ -4034,7 +4133,7 @@ void Security_context::destroy()
}
if (user != delayed_user)
{
- my_free(user);
+ my_free((char*) user);
user= NULL;
}
@@ -4044,7 +4143,7 @@ void Security_context::destroy()
external_user= NULL;
}
- my_free(ip);
+ my_free((char*) ip);
ip= NULL;
}
@@ -4060,7 +4159,7 @@ void Security_context::skip_grants()
bool Security_context::set_user(char *user_arg)
{
- my_free(user);
+ my_free((char*) user);
user= my_strdup(user_arg, MYF(0));
return user == 0;
}
@@ -4118,9 +4217,9 @@ bool Security_context::set_user(char *user_arg)
bool
Security_context::
change_security_context(THD *thd,
- LEX_STRING *definer_user,
- LEX_STRING *definer_host,
- LEX_STRING *db,
+ LEX_CSTRING *definer_user,
+ LEX_CSTRING *definer_host,
+ LEX_CSTRING *db,
Security_context **backup)
{
bool needs_change;
@@ -5293,8 +5392,8 @@ void THD::get_definer(LEX_USER *definer, bool role)
if (slave_thread && has_invoker())
#endif
{
- definer->user = invoker_user;
- definer->host= invoker_host;
+ definer->user= invoker.user;
+ definer->host= invoker.host;
definer->reset_auth();
}
else
@@ -5676,7 +5775,7 @@ int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg)
int THD::decide_logging_format(TABLE_LIST *tables)
{
DBUG_ENTER("THD::decide_logging_format");
- DBUG_PRINT("info", ("Query: %s", query()));
+ DBUG_PRINT("info", ("Query: %.*s", (uint) query_length(), query()));
DBUG_PRINT("info", ("variables.binlog_format: %lu",
variables.binlog_format));
DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x",
@@ -5843,7 +5942,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
if (prev_write_table && prev_write_table->file->ht !=
table->table->file->ht)
multi_write_engine= TRUE;
- if (table->table->s->non_determinstic_insert)
+ if (table->table->s->non_determinstic_insert &&
+ !(sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE))
has_write_tables_with_unsafe_statements= true;
trans= table->table->file->has_transactions();
@@ -7363,4 +7463,16 @@ bool Discrete_intervals_list::append(Discrete_interval *new_interval)
DBUG_RETURN(0);
}
+
+void AUTHID::copy(MEM_ROOT *mem_root, const LEX_CSTRING *user_name,
+ const LEX_CSTRING *host_name)
+{
+ user.str= strmake_root(mem_root, user_name->str, user_name->length);
+ user.length= user_name->length;
+
+ host.str= strmake_root(mem_root, host_name->str, host_name->length);
+ host.length= host_name->length;
+}
+
+
#endif /* !defined(MYSQL_CLIENT) */
diff --git a/sql/sql_class.h b/sql/sql_class.h
index acd3ff0300e..844db884c05 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -233,14 +233,11 @@ typedef struct st_copy_info {
class Key_part_spec :public Sql_alloc {
public:
- LEX_STRING field_name;
+ LEX_CSTRING field_name;
uint length;
- Key_part_spec(const LEX_STRING &name, uint len)
- : field_name(name), length(len)
+ Key_part_spec(const LEX_CSTRING *name, uint len)
+ : field_name(*name), length(len)
{}
- Key_part_spec(const char *name, const size_t name_len, uint len)
- : length(len)
- { field_name.str= (char *)name; field_name.length= name_len; }
bool operator==(const Key_part_spec& other) const;
/**
Construct a copy of this Key_part_spec. field_name is copied
@@ -303,37 +300,26 @@ public:
enum Keytype type;
KEY_CREATE_INFO key_create_info;
List<Key_part_spec> columns;
- LEX_STRING name;
+ LEX_CSTRING name;
engine_option_value *option_list;
bool generated;
- Key(enum Keytype type_par, const LEX_STRING &name_arg,
+ Key(enum Keytype type_par, const LEX_CSTRING *name_arg,
ha_key_alg algorithm_arg, bool generated_arg, DDL_options_st ddl_options)
:DDL_options(ddl_options),
type(type_par), key_create_info(default_key_create_info),
- name(name_arg), option_list(NULL), generated(generated_arg)
+ name(*name_arg), option_list(NULL), generated(generated_arg)
{
key_create_info.algorithm= algorithm_arg;
}
- Key(enum Keytype type_par, const LEX_STRING &name_arg,
+ Key(enum Keytype type_par, const LEX_CSTRING *name_arg,
KEY_CREATE_INFO *key_info_arg,
- bool generated_arg, List<Key_part_spec> &cols,
+ bool generated_arg, List<Key_part_spec> *cols,
engine_option_value *create_opt, DDL_options_st ddl_options)
:DDL_options(ddl_options),
- type(type_par), key_create_info(*key_info_arg), columns(cols),
- name(name_arg), option_list(create_opt), generated(generated_arg)
+ type(type_par), key_create_info(*key_info_arg), columns(*cols),
+ name(*name_arg), option_list(create_opt), generated(generated_arg)
{}
- Key(enum Keytype type_par, const char *name_arg, size_t name_len_arg,
- KEY_CREATE_INFO *key_info_arg, bool generated_arg,
- List<Key_part_spec> &cols,
- engine_option_value *create_opt, DDL_options_st ddl_options)
- :DDL_options(ddl_options),
- type(type_par), key_create_info(*key_info_arg), columns(cols),
- option_list(create_opt), generated(generated_arg)
- {
- name.str= (char *)name_arg;
- name.length= name_len_arg;
- }
Key(const Key &rhs, MEM_ROOT *mem_root);
virtual ~Key() {}
/* Equality comparison of keys (ignoring name) */
@@ -351,19 +337,18 @@ class Foreign_key: public Key {
public:
enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
-
- LEX_STRING ref_db;
- LEX_STRING ref_table;
+ LEX_CSTRING ref_db;
+ LEX_CSTRING ref_table;
List<Key_part_spec> ref_columns;
uint delete_opt, update_opt, match_opt;
- Foreign_key(const LEX_STRING &name_arg, List<Key_part_spec> &cols,
- const LEX_STRING &ref_db_arg, const LEX_STRING &ref_table_arg,
- List<Key_part_spec> &ref_cols,
+ Foreign_key(const LEX_CSTRING *name_arg, List<Key_part_spec> *cols,
+ const LEX_CSTRING *ref_db_arg, const LEX_CSTRING *ref_table_arg,
+ List<Key_part_spec> *ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg,
DDL_options ddl_options)
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols, NULL,
ddl_options),
- ref_db(ref_db_arg), ref_table(ref_table_arg), ref_columns(ref_cols),
+ ref_db(*ref_db_arg), ref_table(*ref_table_arg), ref_columns(*ref_cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
{
@@ -668,7 +653,7 @@ typedef struct system_variables
CHARSET_INFO *collation_connection;
/* Names. These will be allocated in buffers in thd */
- LEX_STRING default_master_connection;
+ LEX_CSTRING default_master_connection;
/* Error messages */
MY_LOCALE *lc_messages;
@@ -699,6 +684,7 @@ typedef struct system_variables
ulong session_track_transaction_info;
my_bool session_track_schema;
my_bool session_track_state_change;
+ my_bool sequence_read_skip_cache;
ulong threadpool_priority;
} SV;
@@ -755,6 +741,7 @@ typedef struct system_status_var
/* The following are for internal temporary tables */
ulong ha_tmp_update_count;
ulong ha_tmp_write_count;
+ ulong ha_tmp_delete_count;
ulong ha_prepare_count;
ulong ha_icp_attempts;
ulong ha_icp_match;
@@ -1047,7 +1034,7 @@ public:
*/
enum enum_mark_columns mark_used_columns;
- LEX_STRING name; /* name for named prepared statements */
+ LEX_CSTRING name; /* name for named prepared statements */
LEX *lex; // parse tree descriptor
/*
Points to the query associated with this statement. It's const, but
@@ -1145,7 +1132,7 @@ public:
int insert(THD *thd, Statement *statement);
- Statement *find_by_name(LEX_STRING *name)
+ Statement *find_by_name(LEX_CSTRING *name)
{
Statement *stmt;
stmt= (Statement*)my_hash_search(&names_hash, (uchar*)name->str,
@@ -1228,7 +1215,7 @@ public:
ip - client IP
*/
const char *host;
- char *user, *ip;
+ const char *user, *ip;
char priv_user[USERNAME_LENGTH];
char proxy_user[USERNAME_LENGTH + MAX_HOSTNAME + 5];
/* The host privilege we are using */
@@ -1255,9 +1242,9 @@ public:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool
change_security_context(THD *thd,
- LEX_STRING *definer_user,
- LEX_STRING *definer_host,
- LEX_STRING *db,
+ LEX_CSTRING *definer_user,
+ LEX_CSTRING *definer_host,
+ LEX_CSTRING *db,
Security_context **backup);
void
@@ -2214,6 +2201,8 @@ public:
chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK.
*/
HASH ull_hash;
+ /* Hash of used seqeunces (for PREVIOUS value) */
+ HASH sequences;
#ifndef DBUG_OFF
uint dbug_sentry; // watch out for memory corruption
#endif
@@ -2418,6 +2407,8 @@ private:
uint binlog_table_maps;
public:
void issue_unsafe_warnings();
+ void reset_unsafe_warnings()
+ { binlog_unsafe_warning_flags= 0; }
uint get_binlog_table_maps() const {
return binlog_table_maps;
@@ -2874,7 +2865,7 @@ public:
If this is a slave, the name of the connection stored here.
This is used for taging error messages in the log files.
*/
- LEX_STRING connection_name;
+ LEX_CSTRING connection_name;
char default_master_connection_buff[MAX_CONNECTION_NAME+1];
uint8 password; /* 0, 1 or 2 */
uint8 failed_com_change_user;
@@ -3201,6 +3192,7 @@ public:
{
return !MY_TEST(variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES);
}
+ const Type_handler *type_handler_for_date() const;
inline my_time_t query_start() { query_start_used=1; return start_time; }
inline ulong query_start_sec_part()
{ query_start_sec_part_used=1; return start_time_sec_part; }
@@ -3352,7 +3344,20 @@ public:
LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, uint length)
{
if (!(lex_str->str= strmake_root(mem_root, str, length)))
+ {
+ lex_str->length= 0;
+ return 0;
+ }
+ lex_str->length= length;
+ return lex_str;
+ }
+ LEX_CSTRING *make_lex_string(LEX_CSTRING *lex_str, const char* str, uint length)
+ {
+ if (!(lex_str->str= strmake_root(mem_root, str, length)))
+ {
+ lex_str->length= 0;
return 0;
+ }
lex_str->length= length;
return lex_str;
}
@@ -3365,6 +3370,14 @@ public:
return make_lex_string(lex_str, str, length);
}
+ LEX_CSTRING *make_clex_string(const char* str, uint length)
+ {
+ LEX_CSTRING *lex_str;
+ if (!(lex_str= (LEX_CSTRING *)alloc_root(mem_root, sizeof(LEX_CSTRING))))
+ return 0;
+ return make_lex_string(lex_str, str, length);
+ }
+
// Allocate LEX_STRING for character set conversion
bool alloc_lex_string(LEX_STRING *dst, uint length)
{
@@ -3411,6 +3424,20 @@ public:
bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs);
+ /*
+ Create a string literal with optional client->connection conversion.
+ @param str - the string in the client character set
+ @param length - length of the string
+ @param repertoire - the repertoire of the string
+ */
+ Item_string *make_string_literal(const char *str, size_t length,
+ uint repertoire);
+ Item_string *make_string_literal(const Lex_string_with_metadata_st &str)
+ {
+ uint repertoire= str.repertoire(variables.character_set_client);
+ return make_string_literal(str.str, str.length, repertoire);
+ }
+
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, long key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
@@ -3800,7 +3827,7 @@ public:
allocate memory for a deep copy: current database may be freed after
a statement is parsed but before it's executed.
*/
- bool copy_db_to(char **p_db, size_t *p_db_length)
+ bool copy_db_to(const char **p_db, size_t *p_db_length)
{
if (db == NULL)
{
@@ -3881,6 +3908,37 @@ public:
*/
void raise_note_printf(uint code, ...);
+ /**
+ @brief Push an error message into MySQL error stack with line
+ and position information.
+
+ This function provides semantic action implementers with a way
+ to push the famous "You have a syntax error near..." error
+ message into the error stack, which is normally produced only if
+ a parse error is discovered internally by the Bison generated
+ parser.
+ */
+ void parse_error(const char *err_text, const char *yytext)
+ {
+ Lex_input_stream *lip= &m_parser_state->m_lip;
+ if (!yytext)
+ {
+ if (!(yytext= lip->get_tok_start()))
+ yytext= "";
+ }
+ /* Push an error into the error stack */
+ ErrConvString err(yytext, strlen(yytext), variables.character_set_client);
+ my_printf_error(ER_PARSE_ERROR, ER_THD(this, ER_PARSE_ERROR), MYF(0),
+ err_text, err.ptr(), lip->yylineno);
+ }
+ void parse_error(uint err_number, const char *yytext= 0)
+ {
+ parse_error(ER_THD(this, err_number), yytext);
+ }
+ void parse_error()
+ {
+ parse_error(ER_SYNTAX_ERROR);
+ }
private:
/*
Only the implementation of the SIGNAL and RESIGNAL statements
@@ -3907,8 +3965,42 @@ private:
raise_condition(uint sql_errno,
const char* sqlstate,
Sql_condition::enum_warning_level level,
+ const char* msg)
+ {
+ return raise_condition(sql_errno, sqlstate, level,
+ Sql_user_condition_identity(), msg);
+ }
+
+ /**
+ Raise a generic or a user defined SQL condition.
+ @param ucid - the user condition identity
+ (or an empty identity if not a user condition)
+ @param sql_errno - the condition error number
+ @param sqlstate - the condition SQLSTATE
+ @param level - the condition level
+ @param msg - the condition message text
+ @return The condition raised, or NULL
+ */
+ Sql_condition*
+ raise_condition(uint sql_errno,
+ const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const Sql_user_condition_identity &ucid,
const char* msg);
+ Sql_condition*
+ raise_condition(const Sql_condition *cond)
+ {
+ Sql_condition *raised= raise_condition(cond->get_sql_errno(),
+ cond->get_sqlstate(),
+ cond->get_level(),
+ *cond/*Sql_user_condition_identity*/,
+ cond->get_message_text());
+ if (raised)
+ raised->copy_opt_attributes(cond);
+ return raised;
+ }
+
public:
/** Overloaded to guard query/query_length fields */
virtual void set_statement(Statement *stmt);
@@ -3986,14 +4078,14 @@ public:
void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; }
enum need_invoker need_binlog_invoker() { return m_binlog_invoker; }
void get_definer(LEX_USER *definer, bool role);
- void set_invoker(const LEX_STRING *user, const LEX_STRING *host)
+ void set_invoker(const LEX_CSTRING *user, const LEX_CSTRING *host)
{
- invoker_user= *user;
- invoker_host= *host;
+ invoker.user= *user;
+ invoker.host= *host;
}
- LEX_STRING get_invoker_user() { return invoker_user; }
- LEX_STRING get_invoker_host() { return invoker_host; }
- bool has_invoker() { return invoker_user.length > 0; }
+ LEX_CSTRING get_invoker_user() { return invoker.user; }
+ LEX_CSTRING get_invoker_host() { return invoker.host; }
+ bool has_invoker() { return invoker.user.length > 0; }
void print_aborted_warning(uint threshold, const char *reason)
{
@@ -4092,8 +4184,7 @@ private:
TRIGGER or VIEW statements or current user in account management
statements if it is not NULL.
*/
- LEX_STRING invoker_user;
- LEX_STRING invoker_host;
+ AUTHID invoker;
public:
#ifndef EMBEDDED_LIBRARY
@@ -4301,6 +4392,31 @@ public:
current_linfo= 0;
mysql_mutex_unlock(&LOCK_thread_count);
}
+
+ /**
+ Switch to a sublex, to parse a substatement or an expression.
+ */
+ void set_local_lex(sp_lex_local *sublex)
+ {
+ DBUG_ASSERT(lex->sphead);
+ lex= sublex;
+ /* Reset part of parser state which needs this. */
+ m_parser_state->m_yacc.reset_before_substatement();
+ }
+
+ /**
+ Switch back from a sublex (currently pointed by this->lex) to the old lex.
+ Sublex is merged to "oldlex" and this->lex is set to "oldlex".
+
+ This method is called after parsing a substatement or an expression.
+ set_local_lex() must be previously called.
+ @param oldlex - The old lex which was active before set_local_lex().
+ @returns - false on success, true on error (failed to merge LEX's).
+
+ See also sp_head::merge_lex().
+ */
+ bool restore_from_local_lex_to_old_lex(LEX *oldlex);
+
};
inline void add_to_active_threads(THD *thd)
@@ -4372,13 +4488,13 @@ class sql_exchange :public Sql_alloc
{
public:
enum enum_filetype filetype; /* load XML, Added by Arnold & Erik */
- char *file_name;
+ const char *file_name;
String *field_term,*enclosed,*line_term,*line_start,*escaped;
bool opt_enclosed;
bool dumpfile;
ulong skip_lines;
CHARSET_INFO *cs;
- sql_exchange(char *name, bool dumpfile_flag,
+ sql_exchange(const char *name, bool dumpfile_flag,
enum_filetype filetype_arg= FILETYPE_CSV);
bool escaped_given(void);
};
@@ -4877,17 +4993,22 @@ public:
};
-class select_union :public select_result_interceptor
+class select_unit :public select_result_interceptor
{
+ uint curr_step, prev_step, curr_sel;
+ enum sub_select_type step;
public:
+ Item_int *intersect_mark;
TMP_TABLE_PARAM tmp_table_param;
int write_err; /* Error code from the last send_data->ha_write_row call. */
-public:
TABLE *table;
ha_rows records;
- select_union(THD *thd_arg):
- select_result_interceptor(thd_arg), write_err(0), table(0), records(0)
+ select_unit(THD *thd_arg):
+ select_result_interceptor(thd_arg),
+ curr_step(0), prev_step(0), curr_sel(UINT_MAX),
+ step(UNION_TYPE), intersect_mark(0), write_err(0), table(0),
+ records(0)
{ tmp_table_param.init(); }
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
/**
@@ -4909,12 +5030,13 @@ public:
const char *alias,
bool bit_fields_as_long,
bool create_table,
- bool keep_row_order= FALSE);
+ bool keep_row_order,
+ uint hidden);
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
+ void change_select();
};
-
-class select_union_recursive :public select_union
+class select_union_recursive :public select_unit
{
public:
/* The temporary table with the new records generated by one iterative step */
@@ -4925,7 +5047,7 @@ class select_union_recursive :public select_union
List<TABLE> rec_tables;
select_union_recursive(THD *thd_arg):
- select_union(thd_arg),
+ select_unit(thd_arg),
incr_table(0), first_rec_table_to_update(0) {};
int send_data(List<Item> &items);
@@ -4934,7 +5056,8 @@ class select_union_recursive :public select_union
const char *alias,
bool bit_fields_as_long,
bool create_table,
- bool keep_row_order= FALSE);
+ bool keep_row_order,
+ uint hidden);
void cleanup();
};
@@ -4951,7 +5074,7 @@ class select_union_recursive :public select_union
have a global ORDER BY clause. @see st_select_lex_unit::prepare().
*/
-class select_union_direct :public select_union
+class select_union_direct :public select_unit
{
private:
/* Result object that receives all rows */
@@ -4977,7 +5100,7 @@ public:
ha_rows send_records;
select_union_direct(THD *thd_arg, select_result *result_arg,
SELECT_LEX *last_select_lex_arg):
- select_union(thd_arg), result(result_arg),
+ select_unit(thd_arg), result(result_arg),
last_select_lex(last_select_lex_arg),
done_send_result_set_metadata(false), done_initialize_tables(false),
limit_found_rows(0)
@@ -5060,7 +5183,7 @@ public:
about NULLs.
*/
-class select_materialize_with_stats : public select_union
+class select_materialize_with_stats : public select_unit
{
protected:
class Column_statistics
@@ -5093,14 +5216,15 @@ protected:
void reset();
public:
- select_materialize_with_stats(THD *thd_arg): select_union(thd_arg)
+ select_materialize_with_stats(THD *thd_arg): select_unit(thd_arg)
{ tmp_table_param.init(); }
bool create_result_table(THD *thd, List<Item> *column_types,
bool is_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long,
bool create_table,
- bool keep_row_order= FALSE);
+ bool keep_row_order,
+ uint hidden);
bool init_result_table(ulonglong select_options);
int send_data(List<Item> &items);
void cleanup();
@@ -5242,22 +5366,23 @@ typedef struct st_sort_buffer {
class Table_ident :public Sql_alloc
{
public:
- LEX_STRING db;
- LEX_STRING table;
+ LEX_CSTRING db;
+ LEX_CSTRING table;
SELECT_LEX_UNIT *sel;
- inline Table_ident(THD *thd, LEX_STRING db_arg, LEX_STRING table_arg,
+ inline Table_ident(THD *thd, const LEX_CSTRING *db_arg,
+ const LEX_CSTRING *table_arg,
bool force)
- :table(table_arg), sel((SELECT_LEX_UNIT *)0)
+ :table(*table_arg), sel((SELECT_LEX_UNIT *)0)
{
if (!force && (thd->client_capabilities & CLIENT_NO_SCHEMA))
- db.str=0;
+ db= null_clex_str;
else
- db= db_arg;
+ db= *db_arg;
}
- inline Table_ident(LEX_STRING table_arg)
- :table(table_arg), sel((SELECT_LEX_UNIT *)0)
+ inline Table_ident(const LEX_CSTRING *table_arg)
+ :table(*table_arg), sel((SELECT_LEX_UNIT *)0)
{
- db.str=0;
+ db= null_clex_str;
}
/*
This constructor is used only for the case when we create a derived
@@ -5274,19 +5399,43 @@ public:
table.length=1;
}
bool is_derived_table() const { return MY_TEST(sel); }
- inline void change_db(char *db_name)
+ inline void change_db(LEX_CSTRING *db_name)
{
- db.str= db_name; db.length= (uint) strlen(db_name);
+ db= *db_name;
}
};
+
+class Qualified_column_ident: public Table_ident
+{
+public:
+ LEX_CSTRING m_column;
+public:
+ Qualified_column_ident(const LEX_CSTRING *column)
+ :Table_ident(&null_clex_str),
+ m_column(*column)
+ { }
+ Qualified_column_ident(const LEX_CSTRING *table, const LEX_CSTRING *column)
+ :Table_ident(table),
+ m_column(*column)
+ { }
+ Qualified_column_ident(THD *thd,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table,
+ const LEX_CSTRING *column)
+ :Table_ident(thd, db, table, false),
+ m_column(*column)
+ { }
+};
+
+
// this is needed for user_vars hash
class user_var_entry
{
CHARSET_INFO *m_charset;
public:
user_var_entry() {} /* Remove gcc warning */
- LEX_STRING name;
+ LEX_CSTRING name;
char *value;
ulong length;
query_id_t update_query_id, used_query_id;
@@ -5301,7 +5450,7 @@ class user_var_entry
void set_charset(CHARSET_INFO *cs) { m_charset= cs; }
};
-user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
+user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
bool create_if_not_exists);
class SORT_INFO;
@@ -5389,32 +5538,52 @@ public:
class my_var : public Sql_alloc {
public:
- const LEX_STRING name;
+ const LEX_CSTRING name;
enum type { SESSION_VAR, LOCAL_VAR, PARAM_VAR };
type scope;
- my_var(const LEX_STRING& j, enum type s) : name(j), scope(s) { }
+ my_var(const LEX_CSTRING *j, enum type s) : name(*j), scope(s) { }
virtual ~my_var() {}
virtual bool set(THD *thd, Item *val) = 0;
+ virtual class my_var_sp *get_my_var_sp() { return NULL; }
};
class my_var_sp: public my_var {
+ const Type_handler *m_type_handler;
public:
uint offset;
- enum_field_types type;
/*
Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling.
*/
sp_head *sp;
- my_var_sp(const LEX_STRING& j, uint o, enum_field_types t, sp_head *s)
- : my_var(j, LOCAL_VAR), offset(o), type(t), sp(s) { }
+ my_var_sp(const LEX_CSTRING *j, uint o, const Type_handler *type_handler,
+ sp_head *s)
+ : my_var(j, LOCAL_VAR), m_type_handler(type_handler), offset(o), sp(s) { }
~my_var_sp() { }
bool set(THD *thd, Item *val);
+ my_var_sp *get_my_var_sp() { return this; }
+ const Type_handler *type_handler() const { return m_type_handler; }
+};
+
+/*
+ This class handles fields of a ROW SP variable when it's used as a OUT
+ parameter in a stored procedure.
+*/
+class my_var_sp_row_field: public my_var_sp
+{
+ uint m_field_offset;
+public:
+ my_var_sp_row_field(const LEX_CSTRING *varname, const LEX_CSTRING *fieldname,
+ uint var_idx, uint field_idx, sp_head *s)
+ :my_var_sp(varname, var_idx, &type_handler_double/*Not really used*/, s),
+ m_field_offset(field_idx)
+ { }
+ bool set(THD *thd, Item *val);
};
class my_var_user: public my_var {
public:
- my_var_user(const LEX_STRING& j)
+ my_var_user(const LEX_CSTRING *j)
: my_var(j, SESSION_VAR) { }
~my_var_user() { }
bool set(THD *thd, Item *val);
@@ -5422,10 +5591,13 @@ public:
class select_dumpvar :public select_result_interceptor {
ha_rows row_count;
+ my_var_sp *m_var_sp_row; // Not NULL if SELECT INTO row_type_sp_variable
+ bool send_data_to_var_list(List<Item> &items);
public:
List<my_var> var_list;
- select_dumpvar(THD *thd_arg): select_result_interceptor(thd_arg)
- { var_list.empty(); row_count= 0; }
+ select_dumpvar(THD *thd_arg)
+ :select_result_interceptor(thd_arg), row_count(0), m_var_sp_row(NULL)
+ { var_list.empty(); }
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
@@ -5552,6 +5724,14 @@ public:
SP Bulk execution optimized
*/
#define CF_SP_BULK_OPTIMIZED (1U << 20)
+/**
+ If command creates or drops a table
+*/
+#define CF_SCHEMA_CHANGE (1U << 21)
+/**
+ If command creates or drops a database
+*/
+#define CF_DB_CHANGE (1U << 22)
/* Bits in server_command_flags */
@@ -5665,6 +5845,17 @@ inline int handler::ha_write_tmp_row(uchar *buf)
return error;
}
+inline int handler::ha_delete_tmp_row(uchar *buf)
+{
+ int error;
+ MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
+ increment_statistics(&SSV::ha_tmp_delete_count);
+ TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_DELETE_ROW, MAX_KEY, 0,
+ { error= delete_row(buf); })
+ MYSQL_DELETE_ROW_DONE(error);
+ return error;
+}
+
inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data)
{
int error;
@@ -5746,6 +5937,84 @@ class Sql_mode_save
sql_mode_t old_mode; // SQL mode saved at construction time.
};
+
+/**
+ This class resembles the SQL Standard schema qualified object name:
+ <schema qualified name> ::= [ <schema name> <period> ] <qualified identifier>
+*/
+class Database_qualified_name
+{
+public:
+ LEX_CSTRING m_db;
+ LEX_CSTRING m_name;
+ Database_qualified_name(const LEX_CSTRING *db, const LEX_CSTRING *name)
+ :m_db(*db), m_name(*name)
+ { }
+ Database_qualified_name(const char *db, size_t db_length,
+ const char *name, size_t name_length)
+ {
+ m_db.str= db;
+ m_db.length= db_length;
+ m_name.str= name;
+ m_name.length= name_length;
+ }
+
+ bool eq(const Database_qualified_name *other) const
+ {
+ CHARSET_INFO *cs= lower_case_table_names ?
+ &my_charset_utf8_general_ci :
+ &my_charset_utf8_bin;
+ return
+ m_db.length == other->m_db.length &&
+ m_name.length == other->m_name.length &&
+ !my_strnncoll(cs,
+ (const uchar *) m_db.str, m_db.length,
+ (const uchar *) other->m_db.str, other->m_db.length) &&
+ !my_strnncoll(cs,
+ (const uchar *) m_name.str, m_name.length,
+ (const uchar *) other->m_name.str, other->m_name.length);
+ }
+ // Export db and name as a qualified name string: 'db.name'
+ size_t make_qname(char *dst, size_t dstlen) const
+ {
+ return my_snprintf(dst, dstlen, "%.*s.%.*s",
+ (int) m_db.length, m_db.str,
+ (int) m_name.length, m_name.str);
+ }
+ // Export db and name as a qualified name string, allocate on mem_root.
+ bool make_qname(THD *thd, LEX_CSTRING *dst) const
+ {
+ const uint dot= !!m_db.length;
+ char *tmp;
+ /* format: [database + dot] + name + '\0' */
+ dst->length= m_db.length + dot + m_name.length;
+ if (!(dst->str= tmp= (char*) thd->alloc(dst->length + 1)))
+ return true;
+ sprintf(tmp, "%.*s%.*s%.*s",
+ (int) m_db.length, (m_db.length ? m_db.str : ""),
+ dot, ".",
+ (int) m_name.length, m_name.str);
+ DBUG_ASSERT(ok_for_lower_case_names(m_db.str));
+ return false;
+ }
+};
+
+
+class ErrConvDQName: public ErrConv
+{
+ const Database_qualified_name *m_name;
+public:
+ ErrConvDQName(const Database_qualified_name *name)
+ :m_name(name)
+ { }
+ const char *ptr() const
+ {
+ m_name->make_qname(err_buffer, sizeof(err_buffer));
+ return err_buffer;
+ }
+};
+
+
#endif /* MYSQL_SERVER */
#endif /* SQL_CLASS_INCLUDED */
diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h
index e33f8e443dc..4ae9353d6ff 100644
--- a/sql/sql_cmd.h
+++ b/sql/sql_cmd.h
@@ -96,6 +96,9 @@ enum enum_sql_command {
SQLCOM_ALTER_USER,
SQLCOM_SHOW_CREATE_USER,
SQLCOM_EXECUTE_IMMEDIATE,
+ SQLCOM_CREATE_SEQUENCE,
+ SQLCOM_DROP_SEQUENCE,
+ SQLCOM_ALTER_SEQUENCE,
/*
When a command is added here, be sure it's also added in mysqld.cc
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 35ec7fa74e1..168814bcc81 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -382,7 +382,7 @@ void reset_mqh(LEX_USER *lu, bool get_them= 0)
static const char mysql_system_user[]= "#mysql_system#";
// Returns 'user' if it's not NULL. Returns 'mysql_system_user' otherwise.
-static const char * get_valid_user_string(char* user)
+static const char * get_valid_user_string(const char* user)
{
return user ? user : mysql_system_user;
}
@@ -1108,7 +1108,7 @@ bool login_connection(THD *thd)
/* Updates global user connection stats. */
if (increment_connection_count(thd, TRUE))
{
- my_error(ER_OUTOFMEMORY, MYF(0), 2*sizeof(USER_STATS));
+ my_error(ER_OUTOFMEMORY, MYF(0), (int) (2*sizeof(USER_STATS)));
error= 1;
goto exit;
}
diff --git a/sql/sql_connect.h b/sql/sql_connect.h
index 9cd31814ad7..364be401944 100644
--- a/sql/sql_connect.h
+++ b/sql/sql_connect.h
@@ -57,7 +57,6 @@ public:
class THD;
-typedef struct st_lex_user LEX_USER;
typedef struct user_conn USER_CONN;
void init_max_user_conn(void);
diff --git a/sql/sql_const.h b/sql/sql_const.h
index 95960ac131a..8d5f56de6b0 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -115,6 +115,7 @@
#define MAX_ACCEPT_RETRY 10 // Test accept this many times
#define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16
+#define SEQUENCES_HASH_SIZE 16
#define TABLE_OPEN_CACHE_MIN 400
#define TABLE_OPEN_CACHE_DEFAULT 2000
#define TABLE_DEF_CACHE_DEFAULT 400
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 1b14c5b68b7..c163044547f 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -735,8 +735,7 @@ bool With_clause::prepare_unreferenced_elements(THD *thd)
bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end)
{
unparsed_spec.length= spec_end - spec_start;
- unparsed_spec.str= (char*) thd->memdup(spec_start, unparsed_spec.length+1);
- unparsed_spec.str[unparsed_spec.length]= '\0';
+ unparsed_spec.str= thd->strmake(spec_start, unparsed_spec.length);
if (!unparsed_spec.str)
{
@@ -806,7 +805,7 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
TABLE_LIST *spec_tables_tail;
st_select_lex *with_select;
- if (parser_state.init(thd, unparsed_spec.str, unparsed_spec.length))
+ if (parser_state.init(thd, (char*) unparsed_spec.str, unparsed_spec.length))
goto err;
lex_start(thd);
with_select= &lex->select_lex;
@@ -888,9 +887,9 @@ With_element::rename_columns_of_derived_unit(THD *thd,
if (column_list.elements) // The column list is optional
{
List_iterator_fast<Item> it(select->item_list);
- List_iterator_fast<LEX_STRING> nm(column_list);
+ List_iterator_fast<LEX_CSTRING> nm(column_list);
Item *item;
- LEX_STRING *name;
+ LEX_CSTRING *name;
if (column_list.elements != select->item_list.elements)
{
diff --git a/sql/sql_cte.h b/sql/sql_cte.h
index 64b2f1cb1c8..85676df9d39 100644
--- a/sql/sql_cte.h
+++ b/sql/sql_cte.h
@@ -4,7 +4,7 @@
#include "sql_lex.h"
#include "sql_select.h"
-class select_union;
+class select_unit;
struct st_unit_ctxt_elem;
@@ -73,7 +73,7 @@ private:
Unparsed specification of the query that specifies this element.
It used to build clones of the specification if they are needed.
*/
- LEX_STRING unparsed_spec;
+ LEX_CSTRING unparsed_spec;
/* Return the map where 1 is set only in the position for this element */
table_map get_elem_map() { return (table_map) 1 << number; }
@@ -83,14 +83,14 @@ public:
The name of the table introduced by this with elememt. The name
can be used in FROM lists of the queries in the scope of the element.
*/
- LEX_STRING *query_name;
+ LEX_CSTRING *query_name;
/*
Optional list of column names to name the columns of the table introduced
by this with element. It is used in the case when the names are not
inherited from the query that specified the table. Otherwise the list is
always empty.
*/
- List <LEX_STRING> column_list;
+ List <LEX_CSTRING> column_list;
/* The query that specifies the table introduced by this with element */
st_select_lex_unit *spec;
/*
@@ -132,8 +132,8 @@ public:
/* List of Item_subselects containing recursive references to this CTE */
SQL_I_List<Item_subselect> sq_with_rec_ref;
- With_element(LEX_STRING *name,
- List <LEX_STRING> list,
+ With_element(LEX_CSTRING *name,
+ List <LEX_CSTRING> list,
st_select_lex_unit *unit)
: next(NULL), base_dep_map(0), derived_dep_map(0),
sq_dep_map(0), work_dep_map(0), mutually_recursive(0),
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 118c6f23cb0..40eb7046108 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -53,6 +53,10 @@ public:
virtual int open(JOIN *join __attribute__((unused)));
virtual void fetch(ulong num_rows);
virtual void close();
+ bool export_structure(THD *thd, Row_definition_list *defs)
+ {
+ return table->export_structure(thd, defs);
+ }
virtual ~Materialized_cursor();
void on_table_fill_finished();
@@ -68,13 +72,13 @@ public:
create a Materialized_cursor.
*/
-class Select_materialize: public select_union
+class Select_materialize: public select_unit
{
select_result *result; /**< the result object of the caller (PS or SP) */
public:
Materialized_cursor *materialized_cursor;
Select_materialize(THD *thd_arg, select_result *result_arg):
- select_union(thd_arg), result(result_arg), materialized_cursor(0) {}
+ select_unit(thd_arg), result(result_arg), materialized_cursor(0) {}
virtual bool send_result_set_metadata(List<Item> &list, uint flags);
bool send_eof()
{
@@ -436,7 +440,7 @@ bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
if (create_result_table(unit->thd, unit->get_column_types(true),
FALSE,
thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS,
- "", FALSE, TRUE, TRUE))
+ "", FALSE, TRUE, TRUE, 0))
return TRUE;
materialized_cursor= new (&table->mem_root)
diff --git a/sql/sql_cursor.h b/sql/sql_cursor.h
index bff47d654b3..6fa72a2005d 100644
--- a/sql/sql_cursor.h
+++ b/sql/sql_cursor.h
@@ -54,6 +54,11 @@ public:
virtual int open(JOIN *top_level_join)= 0;
virtual void fetch(ulong num_rows)= 0;
virtual void close()= 0;
+ virtual bool export_structure(THD *thd, Row_definition_list *defs)
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
virtual ~Server_side_cursor();
static void operator delete(void *ptr, size_t size);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 813a17cdfdb..f91b92b1d4f 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -53,16 +53,16 @@ const char *del_exts[]= {".BAK", ".opt", NullS};
static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
-static bool find_db_tables_and_rm_known_files(THD *, MY_DIR *, char *,
+static bool find_db_tables_and_rm_known_files(THD *, MY_DIR *, const char *,
const char *, TABLE_LIST **);
long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path);
static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error);
static void mysql_change_db_impl(THD *thd,
- LEX_STRING *new_db_name,
+ LEX_CSTRING *new_db_name,
ulong new_db_access,
CHARSET_INFO *new_db_charset);
-static bool mysql_rm_db_internal(THD *thd, char *db,
+static bool mysql_rm_db_internal(THD *thd, const char *db,
bool if_exists, bool silent);
@@ -122,8 +122,8 @@ uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
Helper function to write a query to binlog used by mysql_rm_db()
*/
-static inline int write_to_binlog(THD *thd, char *query, uint q_len,
- char *db, uint db_len)
+static inline int write_to_binlog(THD *thd, const char *query, uint q_len,
+ const char *db, uint db_len)
{
Query_log_event qinfo(thd, query, q_len, FALSE, TRUE, FALSE, 0);
qinfo.db= db;
@@ -566,7 +566,7 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
*/
static int
-mysql_create_db_internal(THD *thd, char *db,
+mysql_create_db_internal(THD *thd, const char *db,
const DDL_options_st &options,
Schema_specification_st *create_info,
bool silent)
@@ -583,15 +583,8 @@ mysql_create_db_internal(THD *thd, char *db,
DBUG_RETURN(-1);
}
- char db_tmp[SAFE_NAME_LEN], *dbnorm;
- if (lower_case_table_names)
- {
- strmake_buf(db_tmp, db);
- my_casedn_str(system_charset_info, db_tmp);
- dbnorm= db_tmp;
- }
- else
- dbnorm= db;
+ char db_tmp[SAFE_NAME_LEN];
+ const char *dbnorm= normalize_db_name(db, db_tmp, sizeof(db_tmp));
if (lock_schema_name(thd, dbnorm))
DBUG_RETURN(-1);
@@ -771,7 +764,7 @@ exit:
}
-int mysql_create_db(THD *thd, char *db,
+int mysql_create_db(THD *thd, const char *db,
const DDL_options_st &options,
const Schema_specification_st *create_info)
{
@@ -812,7 +805,7 @@ bool mysql_alter_db(THD *thd, const char *db,
*/
static bool
-mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent)
+mysql_rm_db_internal(THD *thd, const char *db, bool if_exists, bool silent)
{
ulong deleted_tables= 0;
bool error= true, rm_mysql_schema;
@@ -824,15 +817,8 @@ mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent)
Drop_table_error_handler err_handler;
DBUG_ENTER("mysql_rm_db");
- char db_tmp[SAFE_NAME_LEN], *dbnorm;
- if (lower_case_table_names)
- {
- strmake_buf(db_tmp, db);
- my_casedn_str(system_charset_info, db_tmp);
- dbnorm= db_tmp;
- }
- else
- dbnorm= db;
+ char db_tmp[SAFE_NAME_LEN];
+ const char *dbnorm= normalize_db_name(db, db_tmp, sizeof(db_tmp));
if (lock_schema_name(thd, dbnorm))
DBUG_RETURN(true);
@@ -898,8 +884,8 @@ mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent)
{
for (table= tables; table; table= table->next_local)
{
- LEX_STRING db_name= { table->db, table->db_length };
- LEX_STRING table_name= { table->table_name, table->table_name_length };
+ LEX_CSTRING db_name= { table->db, table->db_length };
+ LEX_CSTRING table_name= { table->table_name, table->table_name_length };
if (table->open_type == OT_BASE_ONLY ||
!thd->find_temporary_table(table))
(void) delete_statistics_for_table(thd, &db_name, &table_name);
@@ -916,7 +902,8 @@ mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent)
thd->push_internal_handler(&err_handler);
if (!thd->killed &&
!(tables &&
- mysql_rm_table_no_locks(thd, tables, true, false, true, true, false)))
+ mysql_rm_table_no_locks(thd, tables, true, false, true, false, true,
+ false)))
{
/*
We temporarily disable the binary log while dropping the objects
@@ -1010,7 +997,8 @@ update_binlog:
if (ha_table_exists(thd, tbl->db, tbl->table_name))
continue;
- my_snprintf(quoted_name, sizeof(quoted_name), "%`s", tbl->table_name);
+ my_snprintf(quoted_name, sizeof(quoted_name), quoted_string,
+ tbl->table_name);
tbl_name_len= strlen(quoted_name) + 1; /* +1 for the comma */
if (query_pos + tbl_name_len + 1 >= query_end)
{
@@ -1061,25 +1049,25 @@ exit:
}
-bool mysql_rm_db(THD *thd,char *db, bool if_exists)
+bool mysql_rm_db(THD *thd, const char *db, bool if_exists)
{
return mysql_rm_db_internal(thd, db, if_exists, false);
}
static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
- char *dbname,
+ const char *dbname,
const char *path,
TABLE_LIST **tables)
{
char filePath[FN_REFLEN];
- LEX_STRING db= { dbname, strlen(dbname) };
+ LEX_CSTRING db= { dbname, strlen(dbname) };
TABLE_LIST *tot_list=0, **tot_list_next_local, **tot_list_next_global;
DBUG_ENTER("find_db_tables_and_rm_known_files");
DBUG_PRINT("enter",("path: %s", path));
/* first, get the list of tables */
- Dynamic_array<LEX_STRING*> files(dirp->number_of_files);
+ Dynamic_array<LEX_CSTRING*> files(dirp->number_of_files);
Discovered_table_list tl(thd, &files);
if (ha_discover_table_names(thd, &db, dirp, &tl, true))
DBUG_RETURN(1);
@@ -1089,7 +1077,7 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
for (size_t idx=0; idx < files.elements(); idx++)
{
- LEX_STRING *table= files.at(idx);
+ LEX_CSTRING *table= files.at(idx);
/* Drop the table nicely */
TABLE_LIST *table_list=(TABLE_LIST*)thd->calloc(sizeof(*table_list));
@@ -1105,7 +1093,7 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
/* To be able to correctly look up the table in the table cache. */
if (lower_case_table_names)
table_list->table_name_length= my_casedn_str(files_charset_info,
- table_list->table_name);
+ (char*) table_list->table_name);
table_list->alias= table_list->table_name; // If lower_case_table_names=2
table_list->mdl_request.init(MDL_key::TABLE, table_list->db,
@@ -1311,7 +1299,7 @@ err:
*/
static void mysql_change_db_impl(THD *thd,
- LEX_STRING *new_db_name,
+ LEX_CSTRING *new_db_name,
ulong new_db_access,
CHARSET_INFO *new_db_charset)
{
@@ -1343,7 +1331,7 @@ static void mysql_change_db_impl(THD *thd,
the previous database name, we should do it explicitly.
*/
thd->set_db(NULL, 0);
- thd->reset_db(new_db_name->str, new_db_name->length);
+ thd->reset_db(const_cast<char*>(new_db_name->str), new_db_name->length);
}
/* 2. Update security context. */
@@ -1455,9 +1443,10 @@ static void backup_current_db_name(THD *thd,
@retval TRUE Error
*/
-bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
+bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
+ bool force_switch)
{
- LEX_STRING new_db_file_name;
+ LEX_CSTRING new_db_file_name;
Security_context *sctx= thd->security_ctx;
ulong db_access= sctx->db_access;
@@ -1520,12 +1509,13 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
It's next to impossible however to get this error when we are called
from sp_head::execute(). But let's switch the current database to NULL
in this case to be sure.
+ The cast below ok here as new_db_file_name was just allocated
*/
- if (check_db_name(&new_db_file_name))
+ if (check_db_name((LEX_STRING*) &new_db_file_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
- my_free(new_db_file_name.str);
+ my_free(const_cast<char*>(new_db_file_name.str));
if (force_switch)
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
@@ -1559,7 +1549,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
new_db_file_name.str);
general_log_print(thd, COM_INIT_DB, ER_THD(thd, ER_DBACCESS_DENIED_ERROR),
sctx->priv_user, sctx->priv_host, new_db_file_name.str);
- my_free(new_db_file_name.str);
+ my_free(const_cast<char*>(new_db_file_name.str));
DBUG_RETURN(TRUE);
}
#endif
@@ -1576,7 +1566,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
ER_BAD_DB_ERROR, ER_THD(thd, ER_BAD_DB_ERROR),
new_db_file_name.str);
- my_free(new_db_file_name.str);
+ my_free(const_cast<char*>(new_db_file_name.str));
/* Change db to NULL. */
@@ -1590,7 +1580,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
/* Report an error and free new_db_file_name. */
my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
- my_free(new_db_file_name.str);
+ my_free(const_cast<char*>(new_db_file_name.str));
/* The operation failed. */
@@ -1635,7 +1625,7 @@ done:
*/
bool mysql_opt_change_db(THD *thd,
- const LEX_STRING *new_db_name,
+ const LEX_CSTRING *new_db_name,
LEX_STRING *saved_db_name,
bool force_switch,
bool *cur_db_changed)
@@ -1665,7 +1655,8 @@ bool mysql_opt_change_db(THD *thd,
@param old_db 5.0 database name, in #mysql50#name format
@return 0 on success, 1 on error
*/
-bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
+
+bool mysql_upgrade_db(THD *thd, LEX_CSTRING *old_db)
{
int error= 0, change_to_newdb= 0;
char path[FN_REFLEN+16];
@@ -1674,7 +1665,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
MY_DIR *dirp;
TABLE_LIST *table_list;
SELECT_LEX *sl= thd->lex->current_select;
- LEX_STRING new_db;
+ LEX_CSTRING new_db;
DBUG_ENTER("mysql_upgrade_db");
if ((old_db->length <= MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
@@ -1730,7 +1721,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
{
FILEINFO *file= dirp->dir_entry + idx;
char *extension, tname[FN_REFLEN + 1];
- LEX_STRING table_str;
+ LEX_CSTRING table_str;
DBUG_PRINT("info",("Examining: %s", file->name));
/* skiping non-FRM files */
@@ -1744,8 +1735,8 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
table_str.length= filename_to_tablename(file->name,
tname, sizeof(tname)-1);
table_str.str= (char*) thd->memdup(tname, table_str.length + 1);
- Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0);
- Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0);
+ Table_ident *old_ident= new Table_ident(thd, old_db, &table_str, 0);
+ Table_ident *new_ident= new Table_ident(thd, &new_db, &table_str, 0);
if (!old_ident || !new_ident ||
!sl->add_table_to_list(thd, old_ident, NULL,
TL_OPTION_UPDATING, TL_IGNORE,
@@ -1892,3 +1883,14 @@ bool check_db_dir_existence(const char *db_name)
return my_access(db_dir_path, F_OK);
}
+
+
+const char *normalize_db_name(const char *db, char *buffer, size_t buffer_size)
+{
+ DBUG_ASSERT(buffer_size > 1);
+ if (!lower_case_table_names)
+ return db;
+ strmake(buffer, db, buffer_size - 1);
+ my_casedn_str(system_charset_info, buffer);
+ return buffer;
+}
diff --git a/sql/sql_db.h b/sql/sql_db.h
index b0d99cc1ba4..a4ada7de6a2 100644
--- a/sql/sql_db.h
+++ b/sql/sql_db.h
@@ -20,18 +20,18 @@
class THD;
-int mysql_create_db(THD *thd, char *db,
+int mysql_create_db(THD *thd, const char *db,
const DDL_options_st &options,
const Schema_specification_st *create);
bool mysql_alter_db(THD *thd, const char *db,
const Schema_specification_st *create);
-bool mysql_rm_db(THD *thd, char *db, bool if_exists);
-bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db);
-bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
+bool mysql_rm_db(THD *thd, const char *db, bool if_exists);
+bool mysql_upgrade_db(THD *thd, LEX_CSTRING *old_db);
+bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
bool force_switch);
bool mysql_opt_change_db(THD *thd,
- const LEX_STRING *new_db_name,
+ const LEX_CSTRING *new_db_name,
LEX_STRING *saved_db_name,
bool force_switch,
bool *cur_db_changed);
@@ -45,6 +45,9 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name);
bool my_dbopt_init(void);
void my_dbopt_cleanup(void);
+const char *normalize_db_name(const char *db, char *buffer,
+ size_t buffer_size);
+
#define MY_DB_OPT_FILE "db.opt"
#endif /* SQL_DB_INCLUDED */
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index eb5f0d7a477..a9275bd39fd 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -45,6 +45,8 @@
// end_read_record
#include "sql_partition.h" // make_used_partitions_str
+#define MEM_STRIP_BUF_SIZE thd->variables.sortbuff_size
+
/*
@brief
Print query plan of a single-table DELETE command
@@ -212,6 +214,22 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
}
+static bool record_should_be_deleted(THD *thd, TABLE *table, SQL_SELECT *sel,
+ Explain_delete *explain)
+{
+ explain->tracker.on_record_read();
+ thd->inc_examined_row_count(1);
+ if (table->vfield)
+ (void) table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_DELETE);
+ if (!sel || sel->skip_record(thd) > 0)
+ {
+ explain->tracker.on_record_after_where();
+ return true;
+ }
+ return false;
+}
+
+
/**
Implement DELETE SQL word.
@@ -244,9 +262,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
bool with_select= !select_lex->item_list.is_empty();
Explain_delete *explain;
Delete_plan query_plan(thd->mem_root);
+ Unique * deltempfile= NULL;
+ bool delete_record, delete_while_scanning;
+ DBUG_ENTER("mysql_delete");
+
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
- DBUG_ENTER("mysql_delete");
create_explain_query(thd->lex, thd->mem_root);
if (open_and_lock_tables(thd, table_list, TRUE, 0))
@@ -275,7 +296,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_plan.updating_a_view= MY_TEST(table_list->view);
if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
- select_lex->item_list, &conds))
+ select_lex->item_list, &conds,
+ &delete_while_scanning))
DBUG_RETURN(TRUE);
if (with_select)
@@ -556,16 +578,48 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
explain= (Explain_delete*)thd->lex->explain->get_upd_del_plan();
explain->tracker.on_scan_init();
+ if (!delete_while_scanning)
+ {
+ /*
+ The table we are going to delete appears in subqueries in the where
+ clause. Instead of deleting the rows, first mark them deleted.
+ */
+ ha_rows tmplimit=limit;
+ deltempfile= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
+ table->file->ref_length,
+ MEM_STRIP_BUF_SIZE);
+ while (!(error=info.read_record(&info)) && !thd->killed &&
+ ! thd->is_error())
+ {
+ if (record_should_be_deleted(thd, table, select, explain))
+ {
+ table->file->position(table->record[0]);
+ if ((error= deltempfile->unique_add((char*) table->file->ref)))
+ {
+ error= 1;
+ goto terminate_delete;
+ }
+ if (!--tmplimit && using_limit)
+ break;
+ }
+ }
+ end_read_record(&info);
+ if (deltempfile->get(table) || table->file->ha_index_or_rnd_end() ||
+ init_read_record(&info, thd, table, 0, &deltempfile->sort, 0, 1, false))
+ {
+ error= 1;
+ goto terminate_delete;
+ }
+ delete_record= true;
+ }
+
while (!(error=info.read_record(&info)) && !thd->killed &&
- ! thd->is_error())
+ ! thd->is_error())
{
- explain->tracker.on_record_read();
- thd->inc_examined_row_count(1);
- if (table->vfield)
- (void) table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_DELETE);
- if (!select || select->skip_record(thd) > 0)
+ if (delete_while_scanning)
+ delete_record= record_should_be_deleted(thd, table, select, explain);
+ if (delete_record)
{
- explain->tracker.on_record_after_where();
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE))
@@ -616,6 +670,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
break;
}
+terminate_delete:
killed_status= thd->killed;
if (killed_status != NOT_KILLED || thd->is_error())
error= 1; // Aborted
@@ -647,6 +702,8 @@ cleanup:
thd->lex->current_select->first_cond_optimization= 0;
}
+ delete deltempfile;
+ deltempfile=NULL;
delete select;
select= NULL;
transactional_table= table->file->has_transactions();
@@ -746,13 +803,15 @@ l
TRUE error
*/
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
- uint wild_num, List<Item> &field_list, Item **conds)
+ uint wild_num, List<Item> &field_list, Item **conds,
+ bool *delete_while_scanning)
{
Item *fake_conds= 0;
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete");
List<Item> all_fields;
+ *delete_while_scanning= true;
thd->lex->allow_sum_func= 0;
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
@@ -772,14 +831,9 @@ l
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
DBUG_RETURN(TRUE);
}
- {
- TABLE_LIST *duplicate;
- if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
- {
- update_non_unique_table_error(table_list, "DELETE", duplicate);
- DBUG_RETURN(TRUE);
- }
- }
+
+ if (unique_table(thd, table_list, table_list->next_global, 0))
+ *delete_while_scanning= false;
if (select_lex->inner_refs_list.elements &&
fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
@@ -794,7 +848,6 @@ l
Delete multiple tables from join
***************************************************************************/
-#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
{
@@ -944,7 +997,7 @@ multi_delete::initialize_tables(JOIN *join)
DBUG_RETURN(1);
table_map tables_to_delete_from=0;
- delete_while_scanning= 1;
+ delete_while_scanning= true;
for (walk= delete_tables; walk; walk= walk->next_local)
{
TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
@@ -957,7 +1010,7 @@ multi_delete::initialize_tables(JOIN *join)
in join, we need to defer delete. So the delete
doesn't interfers with the scaning of results.
*/
- delete_while_scanning= 0;
+ delete_while_scanning= false;
}
}
@@ -993,7 +1046,7 @@ multi_delete::initialize_tables(JOIN *join)
case send_data() shouldn't delete any rows a we may touch
the rows in the deleted table many times
*/
- delete_while_scanning= 0;
+ delete_while_scanning= false;
}
}
walk= delete_tables;
@@ -1006,10 +1059,9 @@ multi_delete::initialize_tables(JOIN *join)
for (;walk ;walk= walk->next_local)
{
TABLE *table=walk->table;
- *tempfiles_ptr++= new Unique (refpos_order_cmp,
- (void *) table->file,
- table->file->ref_length,
- MEM_STRIP_BUF_SIZE);
+ *tempfiles_ptr++= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
+ table->file->ref_length,
+ MEM_STRIP_BUF_SIZE);
}
init_ftfuncs(thd, thd->lex->current_select, 1);
DBUG_RETURN(thd->is_fatal_error != 0);
diff --git a/sql/sql_delete.h b/sql/sql_delete.h
index 9cd09dc5722..54d6cf146b5 100644
--- a/sql/sql_delete.h
+++ b/sql/sql_delete.h
@@ -27,7 +27,8 @@ typedef class Item COND;
template <typename T> class SQL_I_List;
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
- uint wild_num, List<Item> &field_list, Item **conds);
+ uint wild_num, List<Item> &field_list, Item **conds,
+ bool *delete_while_scanning);
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SQL_I_List<ORDER> *order, ha_rows rows,
ulonglong options, select_result *result);
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 649f745fdc4..96683095336 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -672,7 +672,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
specification has been already prepared (a secondary recursive table
reference.
*/
- if (!(derived->derived_result= new (thd->mem_root) select_union(thd)))
+ if (!(derived->derived_result= new (thd->mem_root) select_unit(thd)))
DBUG_RETURN(TRUE); // out of memory
thd->create_tmp_table_for_derived= TRUE;
res= derived->derived_result->create_result_table(
@@ -680,7 +680,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
(first_select->options |
thd->variables.option_bits |
TMP_TABLE_ALL_COLUMNS),
- derived->alias, FALSE, FALSE);
+ derived->alias, FALSE, FALSE, FALSE, 0);
thd->create_tmp_table_for_derived= FALSE;
if (!res && !derived->table)
@@ -735,7 +735,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
unit->derived= derived;
derived->fill_me= FALSE;
- if (!(derived->derived_result= new (thd->mem_root) select_union(thd)))
+ if (!(derived->derived_result= new (thd->mem_root) select_unit(thd)))
DBUG_RETURN(TRUE); // out of memory
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
@@ -763,7 +763,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
As 'distinct' parameter we always pass FALSE (0), because underlying
query will control distinct condition by itself. Correct test of
- distinct underlying query will be is_union &&
+ distinct underlying query will be is_unit_op &&
!unit->union_distinct->next_select() (i.e. it is union and last distinct
SELECT is last SELECT of UNION).
*/
@@ -774,7 +774,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
thd->variables.option_bits |
TMP_TABLE_ALL_COLUMNS),
derived->alias,
- FALSE, FALSE, FALSE))
+ FALSE, FALSE, FALSE,
+ 0))
{
thd->create_tmp_table_for_derived= FALSE;
goto exit;
@@ -875,7 +876,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_RETURN(FALSE);
lex->current_select= first_select;
- if (unit->is_union())
+ if (unit->is_unit_op())
{
// optimize union without execution
res= unit->optimize();
@@ -940,7 +941,7 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived)
if (table->is_created())
DBUG_RETURN(FALSE);
- select_union *result= derived->derived_result;
+ select_unit *result= derived->derived_result;
if (table->s->db_type() == TMP_ENGINE_HTON)
{
result->tmp_table_param.keyinfo= table->s->key_info;
@@ -1038,7 +1039,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
DBUG_RETURN(FALSE);
/*check that table creation passed without problems. */
DBUG_ASSERT(derived->table && derived->table->is_created());
- select_union *derived_result= derived->derived_result;
+ select_unit *derived_result= derived->derived_result;
SELECT_LEX *save_current_select= lex->current_select;
if (derived_is_recursive)
@@ -1054,7 +1055,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
res= derived->fill_recursive(thd);
}
}
- else if (unit->is_union())
+ else if (unit->is_unit_op())
{
// execute union without clean up
res= unit->exec();
diff --git a/sql/sql_digest.cc b/sql/sql_digest.cc
index 6605d0af0a9..27c33f1c64b 100644
--- a/sql/sql_digest.cc
+++ b/sql/sql_digest.cc
@@ -572,7 +572,7 @@ sql_digest_state* digest_add_token(sql_digest_state *state,
case IDENT_QUOTED:
{
YYSTYPE *lex_token= yylval;
- char *yytext= lex_token->lex_str.str;
+ const char *yytext= lex_token->lex_str.str;
size_t yylen= lex_token->lex_str.length;
/*
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index d14c7b83b77..144cf9d4a30 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -172,70 +172,6 @@ This file contains the implementation of error and warnings related
See WL#2111 (Stored Procedures: Implement GET DIAGNOSTICS)
*/
-Sql_condition::Sql_condition()
- : Sql_alloc(),
- m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
- m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
- m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8_bin),
- m_constraint_schema((const char*) NULL, 0, & my_charset_utf8_bin),
- m_constraint_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_catalog_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_schema_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_table_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_message_text(),
- m_sql_errno(0),
- m_level(Sql_condition::WARN_LEVEL_ERROR),
- m_mem_root(NULL)
-{
- memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
-}
-
-void Sql_condition::init(MEM_ROOT *mem_root)
-{
- DBUG_ASSERT(mem_root != NULL);
- DBUG_ASSERT(m_mem_root == NULL);
- m_mem_root= mem_root;
-}
-
-void Sql_condition::clear()
-{
- m_class_origin.length(0);
- m_subclass_origin.length(0);
- m_constraint_catalog.length(0);
- m_constraint_schema.length(0);
- m_constraint_name.length(0);
- m_catalog_name.length(0);
- m_schema_name.length(0);
- m_table_name.length(0);
- m_column_name.length(0);
- m_cursor_name.length(0);
- m_message_text.length(0);
- m_sql_errno= 0;
- m_level= Sql_condition::WARN_LEVEL_ERROR;
-}
-
-Sql_condition::Sql_condition(MEM_ROOT *mem_root)
- : Sql_alloc(),
- m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
- m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
- m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8_bin),
- m_constraint_schema((const char*) NULL, 0, & my_charset_utf8_bin),
- m_constraint_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_catalog_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_schema_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_table_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
- m_message_text(),
- m_sql_errno(0),
- m_level(Sql_condition::WARN_LEVEL_ERROR),
- m_mem_root(mem_root)
-{
- DBUG_ASSERT(mem_root != NULL);
- memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
-}
static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src)
{
@@ -270,21 +206,6 @@ Sql_condition::copy_opt_attributes(const Sql_condition *cond)
copy_string(m_mem_root, & m_cursor_name, & cond->m_cursor_name);
}
-void
-Sql_condition::set(uint sql_errno, const char* sqlstate,
- Sql_condition::enum_warning_level level, const char* msg)
-{
- DBUG_ASSERT(sql_errno != 0);
- DBUG_ASSERT(sqlstate != NULL);
- DBUG_ASSERT(msg != NULL);
-
- m_sql_errno= sql_errno;
- memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
- m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
-
- set_builtin_message_text(msg);
- m_level= level;
-}
void
Sql_condition::set_builtin_message_text(const char* str)
@@ -312,13 +233,46 @@ Sql_condition::get_message_octet_length() const
return m_message_text.length();
}
-void
-Sql_condition::set_sqlstate(const char* sqlstate)
+
+void Sql_state_errno_level::assign_defaults(const Sql_state_errno *from)
{
- memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
- m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
+ DBUG_ASSERT(from);
+ int sqlerrno= from->get_sql_errno();
+ /*
+ SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
+ */
+ DBUG_ASSERT(from->has_sql_state());
+ set_sqlstate(from);
+ /* SQLSTATE class "00": illegal, rejected in the parser. */
+ DBUG_ASSERT(m_sqlstate[0] != '0' || get_sqlstate()[1] != '0');
+
+ if (Sql_state::is_warning()) /* SQLSTATE class "01": warning. */
+ {
+ m_level= Sql_condition::WARN_LEVEL_WARN;
+ m_sql_errno= sqlerrno ? sqlerrno : ER_SIGNAL_WARN;
+ }
+ else if (Sql_state::is_not_found()) /* SQLSTATE class "02": not found. */
+ {
+ m_level= Sql_condition::WARN_LEVEL_ERROR;
+ m_sql_errno= sqlerrno ? sqlerrno : ER_SIGNAL_NOT_FOUND;
+ }
+ else /* other SQLSTATE classes : error. */
+ {
+ m_level= Sql_condition::WARN_LEVEL_ERROR;
+ m_sql_errno= sqlerrno ? sqlerrno : ER_SIGNAL_EXCEPTION;
+ }
}
+
+void Sql_condition::assign_defaults(THD *thd, const Sql_state_errno *from)
+{
+ if (from)
+ Sql_state_errno_level::assign_defaults(from);
+ if (!get_message_text())
+ set_builtin_message_text(ER(get_sql_errno()));
+}
+
+
Diagnostics_area::Diagnostics_area(bool initialize)
: is_bulk_execution(0), m_main_wi(0, false, initialize)
{
@@ -353,7 +307,8 @@ Diagnostics_area::reset_diagnostics_area()
m_can_overwrite_status= FALSE;
/** Don't take chances in production */
m_message[0]= '\0';
- m_sql_errno= 0;
+ Sql_state_errno::clear();
+ Sql_user_condition_identity::clear();
m_affected_rows= 0;
m_last_insert_id= 0;
m_statement_warn_count= 0;
@@ -452,6 +407,7 @@ Diagnostics_area::set_error_status(uint sql_errno)
set_error_status(sql_errno,
ER(sql_errno),
mysql_errno_to_sqlstate(sql_errno),
+ Sql_user_condition_identity(),
NULL);
}
@@ -465,6 +421,7 @@ Diagnostics_area::set_error_status(uint sql_errno)
@param sql_errno SQL-condition error number
@param message SQL-condition message
@param sqlstate SQL-condition state
+ @param ucid User defined condition identity
@param error_condition SQL-condition object representing the error state
@note Note, that error_condition may be NULL. It happens if a) OOM error is
@@ -475,6 +432,7 @@ void
Diagnostics_area::set_error_status(uint sql_errno,
const char *message,
const char *sqlstate,
+ const Sql_user_condition_identity &ucid,
const Sql_condition *error_condition)
{
DBUG_ENTER("set_error_status");
@@ -501,9 +459,8 @@ Diagnostics_area::set_error_status(uint sql_errno,
return;
#endif
- m_sql_errno= sql_errno;
- memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
- m_sqlstate[SQLSTATE_LENGTH]= '\0';
+ Sql_state_errno::set(sql_errno, sqlstate);
+ Sql_user_condition_identity::set(ucid);
strmake_buf(m_message, message);
get_warning_info()->set_error_condition(error_condition);
@@ -695,8 +652,7 @@ void Warning_info::reserve_space(THD *thd, uint count)
}
Sql_condition *Warning_info::push_warning(THD *thd,
- uint sql_errno, const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ const Sql_condition_identity *value,
const char *msg)
{
Sql_condition *cond= NULL;
@@ -706,14 +662,11 @@ Sql_condition *Warning_info::push_warning(THD *thd,
if (m_allow_unlimited_warnings ||
m_warn_list.elements() < thd->variables.max_error_count)
{
- cond= new (& m_warn_root) Sql_condition(& m_warn_root);
+ cond= new (& m_warn_root) Sql_condition(& m_warn_root, *value, msg);
if (cond)
- {
- cond->set(sql_errno, sqlstate, level, msg);
m_warn_list.push_back(cond);
- }
}
- m_warn_count[(uint) level]++;
+ m_warn_count[(uint) value->get_level()]++;
}
m_current_statement_warn_count++;
@@ -721,13 +674,11 @@ Sql_condition *Warning_info::push_warning(THD *thd,
}
-Sql_condition *Warning_info::push_warning(THD *thd, const Sql_condition *sql_condition)
+Sql_condition *Warning_info::push_warning(THD *thd,
+ const Sql_condition *sql_condition)
{
- Sql_condition *new_condition= push_warning(thd,
- sql_condition->get_sql_errno(),
- sql_condition->get_sqlstate(),
- sql_condition->get_level(),
- sql_condition->get_message_text());
+ Sql_condition *new_condition= push_warning(thd, sql_condition,
+ sql_condition->get_message_text());
if (new_condition)
new_condition->copy_opt_attributes(sql_condition);
@@ -1043,7 +994,7 @@ uint32 convert_error_message(char *to, uint32 to_length, CHARSET_INFO *to_cs,
@retval false if it's bad.
*/
-bool is_sqlstate_valid(const LEX_STRING *sqlstate)
+bool is_sqlstate_valid(const LEX_CSTRING *sqlstate)
{
if (sqlstate->length != 5)
return false;
diff --git a/sql/sql_error.h b/sql/sql_error.h
index 3aef5d38368..f020b9cc789 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -27,15 +27,123 @@
class THD;
class my_decimal;
+class sp_condition_value;
///////////////////////////////////////////////////////////////////////////
-/**
- Representation of a SQL condition.
- A SQL condition can be a completion condition (note, warning),
- or an exception condition (error, not found).
-*/
-class Sql_condition : public Sql_alloc
+class Sql_state
+{
+protected:
+ /**
+ This member is always NUL terminated.
+ */
+ char m_sqlstate[SQLSTATE_LENGTH + 1];
+public:
+ Sql_state()
+ {
+ memset(m_sqlstate, 0, sizeof(m_sqlstate));
+ }
+
+ Sql_state(const char *sqlstate)
+ {
+ set_sqlstate(sqlstate);
+ }
+
+ const char* get_sqlstate() const
+ { return m_sqlstate; }
+
+ void set_sqlstate(const Sql_state *other)
+ {
+ *this= *other;
+ }
+ void set_sqlstate(const char *sqlstate)
+ {
+ memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
+ m_sqlstate[SQLSTATE_LENGTH]= '\0';
+ }
+ bool eq(const Sql_state *other) const
+ {
+ return strcmp(m_sqlstate, other->m_sqlstate) == 0;
+ }
+
+ bool has_sql_state() const { return m_sqlstate[0] != '\0'; }
+
+ /**
+ Checks if this SQL state defines a WARNING condition.
+ Note: m_sqlstate must contain a valid SQL-state.
+
+ @retval true if this SQL state defines a WARNING condition.
+ @retval false otherwise.
+ */
+ inline bool is_warning() const
+ { return m_sqlstate[0] == '0' && m_sqlstate[1] == '1'; }
+
+
+ /**
+ Checks if this SQL state defines a NOT FOUND condition.
+ Note: m_sqlstate must contain a valid SQL-state.
+
+ @retval true if this SQL state defines a NOT FOUND condition.
+ @retval false otherwise.
+ */
+ inline bool is_not_found() const
+ { return m_sqlstate[0] == '0' && m_sqlstate[1] == '2'; }
+
+
+ /**
+ Checks if this SQL state defines an EXCEPTION condition.
+ Note: m_sqlstate must contain a valid SQL-state.
+
+ @retval true if this SQL state defines an EXCEPTION condition.
+ @retval false otherwise.
+ */
+ inline bool is_exception() const
+ { return m_sqlstate[0] != '0' || m_sqlstate[1] > '2'; }
+
+};
+
+
+class Sql_state_errno: public Sql_state
+{
+protected:
+ /**
+ MySQL extension, MYSQL_ERRNO condition item.
+ SQL error number. One of ER_ codes from share/errmsg.txt.
+ Set by set_error_status.
+ */
+ uint m_sql_errno;
+
+public:
+ Sql_state_errno()
+ :m_sql_errno(0)
+ { }
+ Sql_state_errno(uint sql_errno)
+ :m_sql_errno(sql_errno)
+ { }
+ Sql_state_errno(uint sql_errno, const char *sql_state)
+ :Sql_state(sql_state),
+ m_sql_errno(sql_errno)
+ { }
+ /**
+ Get the SQL_ERRNO of this condition.
+ @return the sql error number condition item.
+ */
+ uint get_sql_errno() const
+ { return m_sql_errno; }
+
+ void set(uint sql_errno, const char *sqlstate)
+ {
+ m_sql_errno= sql_errno;
+ set_sqlstate(sqlstate);
+ }
+ void clear()
+ {
+ m_sql_errno= 0;
+ }
+};
+
+
+class Sql_state_errno_level: public Sql_state_errno
{
public:
/*
@@ -47,6 +155,197 @@ public:
enum enum_warning_level
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
+protected:
+ /** Severity (error, warning, note) of this condition. */
+ enum_warning_level m_level;
+
+ void assign_defaults(const Sql_state_errno *value);
+
+public:
+ /**
+ Get the error level of this condition.
+ @return the error level condition item.
+ */
+ enum_warning_level get_level() const
+ { return m_level; }
+
+ Sql_state_errno_level()
+ :m_level(WARN_LEVEL_ERROR)
+ { }
+
+ Sql_state_errno_level(uint sqlerrno, const char* sqlstate,
+ enum_warning_level level)
+ :Sql_state_errno(sqlerrno, sqlstate),
+ m_level(level)
+ { }
+ Sql_state_errno_level(const Sql_state_errno &state_errno,
+ enum_warning_level level)
+ :Sql_state_errno(state_errno),
+ m_level(level)
+ { }
+ void clear()
+ {
+ m_level= WARN_LEVEL_ERROR;
+ Sql_state_errno::clear();
+ }
+};
+
+
+/*
+ class Sql_user_condition_identity.
+ Instances of this class uniquely idetify user defined conditions (EXCEPTION).
+
+ SET sql_mode=ORACLE;
+ CREATE PROCEDURE p1
+ AS
+ a EXCEPTION;
+ BEGIN
+ RAISE a;
+ EXCEPTION
+ WHEN a THEN NULL;
+ END;
+
+ Currently a user defined condition is identified by a pointer to
+ its parse time sp_condition_value instance. This can change when
+ we add packages. See MDEV-10591.
+*/
+class Sql_user_condition_identity
+{
+protected:
+ const sp_condition_value *m_user_condition_value;
+public:
+ Sql_user_condition_identity()
+ :m_user_condition_value(NULL)
+ { }
+ Sql_user_condition_identity(const sp_condition_value *value)
+ :m_user_condition_value(value)
+ { }
+ const sp_condition_value *get_user_condition_value() const
+ { return m_user_condition_value; }
+
+ void set(const Sql_user_condition_identity &identity)
+ {
+ *this= identity;
+ }
+ void clear()
+ {
+ m_user_condition_value= NULL;
+ }
+};
+
+
+/**
+ class Sql_condition_identity.
+ Instances of this class uniquely identify conditions
+ (including user-defined exceptions for sql_mode=ORACLE)
+ and store everything that is needed for handler search
+ purposes in sp_pcontext::find_handler().
+*/
+class Sql_condition_identity: public Sql_state_errno_level,
+ public Sql_user_condition_identity
+{
+public:
+ Sql_condition_identity()
+ { }
+ Sql_condition_identity(const Sql_state_errno_level &st,
+ const Sql_user_condition_identity &ucid)
+ :Sql_state_errno_level(st),
+ Sql_user_condition_identity(ucid)
+ { }
+ Sql_condition_identity(const Sql_state_errno &st,
+ enum_warning_level level,
+ const Sql_user_condition_identity &ucid)
+ :Sql_state_errno_level(st, level),
+ Sql_user_condition_identity(ucid)
+ { }
+ Sql_condition_identity(uint sqlerrno,
+ const char* sqlstate,
+ enum_warning_level level,
+ const Sql_user_condition_identity &ucid)
+ :Sql_state_errno_level(sqlerrno, sqlstate, level),
+ Sql_user_condition_identity(ucid)
+ { }
+ void clear()
+ {
+ Sql_state_errno_level::clear();
+ Sql_user_condition_identity::clear();
+ }
+};
+
+
+class Sql_condition_items
+{
+protected:
+ /** SQL CLASS_ORIGIN condition item. */
+ String m_class_origin;
+
+ /** SQL SUBCLASS_ORIGIN condition item. */
+ String m_subclass_origin;
+
+ /** SQL CONSTRAINT_CATALOG condition item. */
+ String m_constraint_catalog;
+
+ /** SQL CONSTRAINT_SCHEMA condition item. */
+ String m_constraint_schema;
+
+ /** SQL CONSTRAINT_NAME condition item. */
+ String m_constraint_name;
+
+ /** SQL CATALOG_NAME condition item. */
+ String m_catalog_name;
+
+ /** SQL SCHEMA_NAME condition item. */
+ String m_schema_name;
+
+ /** SQL TABLE_NAME condition item. */
+ String m_table_name;
+
+ /** SQL COLUMN_NAME condition item. */
+ String m_column_name;
+
+ /** SQL CURSOR_NAME condition item. */
+ String m_cursor_name;
+
+ Sql_condition_items()
+ :m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_schema((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_catalog_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_schema_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_table_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin)
+ { }
+
+ void clear()
+ {
+ m_class_origin.length(0);
+ m_subclass_origin.length(0);
+ m_constraint_catalog.length(0);
+ m_constraint_schema.length(0);
+ m_constraint_name.length(0);
+ m_catalog_name.length(0);
+ m_schema_name.length(0);
+ m_table_name.length(0);
+ m_column_name.length(0);
+ m_cursor_name.length(0);
+ }
+};
+
+
+/**
+ Representation of a SQL condition.
+ A SQL condition can be a completion condition (note, warning),
+ or an exception condition (error, not found).
+*/
+class Sql_condition : public Sql_alloc,
+ public Sql_condition_identity,
+ public Sql_condition_items
+{
+public:
+
/**
Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits
to WARN_LEVEL_XXX
@@ -69,27 +368,6 @@ public:
*/
int get_message_octet_length() const;
- /**
- Get the SQLSTATE of this condition.
- @return the sql state.
- */
- const char* get_sqlstate() const
- { return m_returned_sqlstate; }
-
- /**
- Get the SQL_ERRNO of this condition.
- @return the sql error number condition item.
- */
- uint get_sql_errno() const
- { return m_sql_errno; }
-
- /**
- Get the error level of this condition.
- @return the error level condition item.
- */
- Sql_condition::enum_warning_level get_level() const
- { return m_level; }
-
private:
/*
The interface of Sql_condition is mostly private, by design,
@@ -116,21 +394,57 @@ private:
This constructor is usefull when allocating arrays.
Note that the init() method should be called to complete the Sql_condition.
*/
- Sql_condition();
+ Sql_condition()
+ :m_mem_root(NULL)
+ { }
/**
Complete the Sql_condition initialisation.
@param mem_root The memory root to use for the condition items
of this condition
*/
- void init(MEM_ROOT *mem_root);
+ void init(MEM_ROOT *mem_root)
+ {
+ DBUG_ASSERT(mem_root != NULL);
+ DBUG_ASSERT(m_mem_root == NULL);
+ m_mem_root= mem_root;
+ }
/**
Constructor.
@param mem_root The memory root to use for the condition items
of this condition
*/
- Sql_condition(MEM_ROOT *mem_root);
+ Sql_condition(MEM_ROOT *mem_root)
+ :m_mem_root(mem_root)
+ {
+ DBUG_ASSERT(mem_root != NULL);
+ }
+
+ Sql_condition(MEM_ROOT *mem_root, const Sql_user_condition_identity &ucid)
+ :Sql_condition_identity(Sql_state_errno_level(), ucid),
+ m_mem_root(mem_root)
+ {
+ DBUG_ASSERT(mem_root != NULL);
+ }
+ /**
+ Constructor for a fixed message text.
+ @param mem_root - memory root
+ @param value - the error number and the sql state for this condition
+ @param level - the error level for this condition
+ @param msg - the message text for this condition
+ */
+ Sql_condition(MEM_ROOT *mem_root,
+ const Sql_condition_identity &value,
+ const char *msg)
+ :Sql_condition_identity(value),
+ m_mem_root(mem_root)
+ {
+ DBUG_ASSERT(mem_root != NULL);
+ DBUG_ASSERT(value.get_sql_errno() != 0);
+ DBUG_ASSERT(msg != NULL);
+ set_builtin_message_text(msg);
+ }
/** Destructor. */
~Sql_condition()
@@ -143,27 +457,12 @@ private:
void copy_opt_attributes(const Sql_condition *cond);
/**
- Set this condition area with a fixed message text.
- @param thd the current thread.
- @param code the error number for this condition.
- @param str the message text for this condition.
- @param level the error level for this condition.
- @param MyFlags additional flags.
- */
- void set(uint sql_errno, const char* sqlstate,
- Sql_condition::enum_warning_level level,
- const char* msg);
-
- /**
Set the condition message test.
@param str Message text, expressed in the character set derived from
the server --language option
*/
void set_builtin_message_text(const char* str);
- /** Set the SQLSTATE of this condition. */
- void set_sqlstate(const char* sqlstate);
-
/** Set the CLASS_ORIGIN of this condition. */
void set_class_origin();
@@ -171,56 +470,27 @@ private:
void set_subclass_origin();
/**
+ Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
+ default values of a condition.
+ @param thd - current thread, to access to localized error messages
+ @param from - copy condition items from here (can be NULL)
+ */
+ void assign_defaults(THD *thd, const Sql_state_errno *from);
+
+ /**
Clear this SQL condition.
*/
- void clear();
+ void clear()
+ {
+ Sql_condition_identity::clear();
+ Sql_condition_items::clear();
+ m_message_text.length(0);
+ }
private:
- /** SQL CLASS_ORIGIN condition item. */
- String m_class_origin;
-
- /** SQL SUBCLASS_ORIGIN condition item. */
- String m_subclass_origin;
-
- /** SQL CONSTRAINT_CATALOG condition item. */
- String m_constraint_catalog;
-
- /** SQL CONSTRAINT_SCHEMA condition item. */
- String m_constraint_schema;
-
- /** SQL CONSTRAINT_NAME condition item. */
- String m_constraint_name;
-
- /** SQL CATALOG_NAME condition item. */
- String m_catalog_name;
-
- /** SQL SCHEMA_NAME condition item. */
- String m_schema_name;
-
- /** SQL TABLE_NAME condition item. */
- String m_table_name;
-
- /** SQL COLUMN_NAME condition item. */
- String m_column_name;
-
- /** SQL CURSOR_NAME condition item. */
- String m_cursor_name;
-
/** Message text, expressed in the character set implied by --language. */
String m_message_text;
- /** MySQL extension, MYSQL_ERRNO condition item. */
- uint m_sql_errno;
-
- /**
- SQL RETURNED_SQLSTATE condition item.
- This member is always NUL terminated.
- */
- char m_returned_sqlstate[SQLSTATE_LENGTH+1];
-
- /** Severity (error, warning, note) of this condition. */
- Sql_condition::enum_warning_level m_level;
-
/** Pointers for participating in the list of conditions. */
Sql_condition *next_in_wi;
Sql_condition **prev_in_wi;
@@ -467,17 +737,13 @@ private:
counters.
@param thd Thread context.
- @param sql_errno SQL-condition error number.
- @param sqlstate SQL-condition state.
- @param level SQL-condition level.
+ @param identity SQL-condition identity
@param msg SQL-condition message.
@return a pointer to the added SQL-condition.
*/
Sql_condition *push_warning(THD *thd,
- uint sql_errno,
- const char* sqlstate,
- Sql_condition::enum_warning_level level,
+ const Sql_condition_identity *identity,
const char* msg);
/**
@@ -634,7 +900,8 @@ public:
Can not be assigned twice per statement.
*/
-class Diagnostics_area
+class Diagnostics_area: public Sql_state_errno,
+ public Sql_user_condition_identity
{
private:
/** The type of the counted and doubly linked list of conditions. */
@@ -686,8 +953,19 @@ public:
void set_error_status(uint sql_errno,
const char *message,
const char *sqlstate,
+ const Sql_user_condition_identity &ucid,
const Sql_condition *error_condition);
+ void set_error_status(uint sql_errno,
+ const char *message,
+ const char *sqlstate,
+ const Sql_condition *error_condition)
+ {
+ set_error_status(sql_errno, message, sqlstate,
+ Sql_user_condition_identity(),
+ error_condition);
+ }
+
void disable_status();
void reset_diagnostics_area();
@@ -722,10 +1000,13 @@ public:
{ m_skip_flush= TRUE; }
uint sql_errno() const
- { DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
+ {
+ DBUG_ASSERT(m_status == DA_ERROR);
+ return Sql_state_errno::get_sql_errno();
+ }
const char* get_sqlstate() const
- { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
+ { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state::get_sqlstate(); }
ulonglong affected_rows() const
{
@@ -746,6 +1027,18 @@ public:
return m_statement_warn_count;
}
+ /**
+ Get the current errno, state and id of the user defined condition
+ and return them as Sql_condition_identity.
+ */
+ Sql_condition_identity get_error_condition_identity() const
+ {
+ DBUG_ASSERT(m_status == DA_ERROR);
+ return Sql_condition_identity(*this /*Sql_state_errno*/,
+ Sql_condition::WARN_LEVEL_ERROR,
+ *this /*Sql_user_condition_identity*/);
+ }
+
/* Used to count any warnings pushed after calling set_ok_status(). */
void increment_warning()
{
@@ -842,13 +1135,22 @@ public:
uint sql_errno_arg,
const char* sqlstate,
Sql_condition::enum_warning_level level,
+ const Sql_user_condition_identity &ucid,
const char* msg)
{
- return get_warning_info()->push_warning(thd,
- sql_errno_arg, sqlstate, level,
- msg);
+ Sql_condition_identity tmp(sql_errno_arg, sqlstate, level, ucid);
+ return get_warning_info()->push_warning(thd, &tmp, msg);
}
+ Sql_condition *push_warning(THD *thd,
+ uint sqlerrno,
+ const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const char* msg)
+ {
+ return push_warning(thd, sqlerrno, sqlstate, level,
+ Sql_user_condition_identity(), msg);
+ }
void mark_sql_conditions_for_removal()
{ get_warning_info()->mark_sql_conditions_for_removal(); }
@@ -888,14 +1190,6 @@ private:
char m_message[MYSQL_ERRMSG_SIZE];
/**
- SQL error number. One of ER_ codes from share/errmsg.txt.
- Set by set_error_status.
- */
- uint m_sql_errno;
-
- char m_sqlstate[SQLSTATE_LENGTH+1];
-
- /**
The number of rows affected by the last statement. This is
semantically close to thd->m_row_count_func, but has a different
life cycle. thd->m_row_count_func stores the value returned by
@@ -950,7 +1244,7 @@ uint32 convert_error_message(char *to, uint32 to_length,
extern const LEX_STRING warning_level_names[];
-bool is_sqlstate_valid(const LEX_STRING *sqlstate);
+bool is_sqlstate_valid(const LEX_CSTRING *sqlstate);
/**
Checks if the specified SQL-state-string defines COMPLETION condition.
This function assumes that the given string contains a valid SQL-state.
@@ -964,43 +1258,4 @@ inline bool is_sqlstate_completion(const char *s)
{ return s[0] == '0' && s[1] == '0'; }
-/**
- Checks if the specified SQL-state-string defines WARNING condition.
- This function assumes that the given string contains a valid SQL-state.
-
- @param s the condition SQLSTATE.
-
- @retval true if the given string defines WARNING condition.
- @retval false otherwise.
-*/
-inline bool is_sqlstate_warning(const char *s)
-{ return s[0] == '0' && s[1] == '1'; }
-
-
-/**
- Checks if the specified SQL-state-string defines NOT FOUND condition.
- This function assumes that the given string contains a valid SQL-state.
-
- @param s the condition SQLSTATE.
-
- @retval true if the given string defines NOT FOUND condition.
- @retval false otherwise.
-*/
-inline bool is_sqlstate_not_found(const char *s)
-{ return s[0] == '0' && s[1] == '2'; }
-
-
-/**
- Checks if the specified SQL-state-string defines EXCEPTION condition.
- This function assumes that the given string contains a valid SQL-state.
-
- @param s the condition SQLSTATE.
-
- @retval true if the given string defines EXCEPTION condition.
- @retval false otherwise.
-*/
-inline bool is_sqlstate_exception(const char *s)
-{ return s[0] != '0' || s[1] > '2'; }
-
-
#endif // SQL_ERROR_H
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 9b474fd5dee..ca276eb87ac 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -29,6 +29,11 @@ const char * STR_DELETING_ALL_ROWS= "Deleting all rows";
const char * STR_IMPOSSIBLE_WHERE= "Impossible WHERE";
const char * STR_NO_ROWS_AFTER_PRUNING= "No matching rows after partition pruning";
+const char *unit_operation_text[4]=
+{
+ "UNIT RESULT","UNION RESULT","INTERSECT RESULT","EXCEPT RESULT"
+};
+
static void write_item(Json_writer *writer, Item *item);
static void append_item_to_str(String *out, Item *item);
@@ -421,8 +426,26 @@ int print_explain_row(select_result_sink *result,
uint Explain_union::make_union_table_name(char *buf)
{
uint childno= 0;
- uint len= 6, lastop= 0;
- memcpy(buf, STRING_WITH_LEN("<union"));
+ uint len, lastop= 0;
+ LEX_CSTRING type;
+ switch (operation)
+ {
+ case OP_MIX:
+ lex_string_set3(&type, STRING_WITH_LEN("<unit"));
+ break;
+ case OP_UNION:
+ lex_string_set3(&type, STRING_WITH_LEN("<union"));
+ break;
+ case OP_INTERSECT:
+ lex_string_set3(&type, STRING_WITH_LEN("<intersect"));
+ break;
+ case OP_EXCEPT:
+ lex_string_set3(&type, STRING_WITH_LEN("<except"));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ memcpy(buf, type.str, (len= type.length));
for (; childno < union_members.elements() && len + lastop + 5 < NAME_LEN;
childno++)
@@ -465,7 +488,7 @@ int Explain_union::print_explain(Explain_query *query,
if (!using_tmp)
return 0;
- /* Print a line with "UNION RESULT" */
+ /* Print a line with "UNIT RESULT" */
List<Item> item_list;
Item *item_null= new (mem_root) Item_null(thd);
@@ -817,6 +840,28 @@ int Explain_basic_join::print_explain(Explain_query *query,
}
+void Explain_select::add_linkage(Json_writer *writer)
+{
+ const char *operation= NULL;
+ switch (linkage)
+ {
+ case UNION_TYPE:
+ operation= "UNION";
+ break;
+ case INTERSECT_TYPE:
+ operation= "INTERSECT";
+ break;
+ case EXCEPT_TYPE:
+ operation= "EXCEPT";
+ break;
+ default:
+ // It is the first or the only SELECT => no operation
+ break;
+ }
+ if (operation)
+ writer->add_member("operation").add_str(operation);
+}
+
void Explain_select::print_explain_json(Explain_query *query,
Json_writer *writer, bool is_analyze)
{
@@ -828,6 +873,7 @@ void Explain_select::print_explain_json(Explain_query *query,
{
writer->add_member("query_block").start_object();
writer->add_member("select_id").add_ll(select_id);
+ add_linkage(writer);
writer->add_member("table").start_object();
writer->add_member("message").add_str(message);
@@ -840,6 +886,7 @@ void Explain_select::print_explain_json(Explain_query *query,
{
writer->add_member("query_block").start_object();
writer->add_member("select_id").add_ll(select_id);
+ add_linkage(writer);
if (is_analyze && time_tracker.get_loops())
{
@@ -1103,7 +1150,8 @@ void Explain_index_use::set(MEM_ROOT *mem_root, KEY *key, uint key_len_arg)
uint len= 0;
for (uint i= 0; i < key->usable_key_parts; i++)
{
- key_parts_list.append_str(mem_root, key->key_part[i].field->field_name);
+ key_parts_list.append_str(mem_root,
+ key->key_part[i].field->field_name.str);
len += key->key_part[i].store_length;
if (len >= key_len_arg)
break;
diff --git a/sql/sql_explain.h b/sql/sql_explain.h
index bfddf40ff33..154769fe289 100644
--- a/sql/sql_explain.h
+++ b/sql/sql_explain.h
@@ -207,6 +207,7 @@ public:
Explain_select(MEM_ROOT *root, bool is_analyze) :
Explain_basic_join(root),
+ linkage(UNSPECIFIED_TYPE),
message(NULL),
having(NULL), having_value(Item::COND_UNDEF),
using_temporary(false), using_filesort(false),
@@ -214,8 +215,11 @@ public:
aggr_tree(NULL)
{}
+ void add_linkage(Json_writer *writer);
+
public:
const char *select_type;
+ enum sub_select_type linkage;
/*
If message != NULL, this is a degenerate join plan, and all subsequent
@@ -316,7 +320,9 @@ public:
/////////////////////////////////////////////////////////////////////////////
-/*
+extern const char *unit_operation_text[4];
+
+/*
Explain structure for a UNION.
A UNION may or may not have "Using filesort".
@@ -332,6 +338,7 @@ public:
{}
enum explain_node_type get_type() { return EXPLAIN_UNION; }
+ unit_common_op operation;
int get_select_id()
{
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 4a27244f5b9..babb09a1267 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -286,7 +286,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
mdl_savepoint= thd->mdl_context.mdl_savepoint();
/* for now HANDLER can be used only for real TABLES */
- tables->required_type= FRMTYPE_TABLE;
+ tables->required_type= TABLE_TYPE_NORMAL;
/*
We use open_tables() here, rather than, say,
@@ -549,7 +549,7 @@ SQL_HANDLER *mysql_ha_find_handler(THD *thd, const char *name)
static bool
mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
- enum enum_ha_read_modes mode, char *keyname,
+ enum enum_ha_read_modes mode, const char *keyname,
List<Item> *key_expr,
Item *cond, bool in_prepare)
{
@@ -671,7 +671,7 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
*/
bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
- enum enum_ha_read_modes mode, char *keyname,
+ enum enum_ha_read_modes mode, const char *keyname,
List<Item> *key_expr,
enum ha_rkey_function ha_rkey_mode, Item *cond,
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
@@ -926,7 +926,8 @@ err0:
*/
SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
- enum enum_ha_read_modes mode, char *keyname,
+ enum enum_ha_read_modes mode,
+ const char *keyname,
List<Item> *key_expr, Item *cond)
{
SQL_HANDLER *handler;
diff --git a/sql/sql_handler.h b/sql/sql_handler.h
index 7fe5ae5bba8..cb1aff1d727 100644
--- a/sql/sql_handler.h
+++ b/sql/sql_handler.h
@@ -68,7 +68,7 @@ struct TABLE_LIST;
bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen);
bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
-bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
+bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes, const char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
void mysql_ha_flush(THD *thd);
void mysql_ha_flush_tables(THD *thd, TABLE_LIST *all_tables);
@@ -78,6 +78,7 @@ void mysql_ha_set_explicit_lock_duration(THD *thd);
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, char *keyname,
+ enum enum_ha_read_modes mode,
+ const char *keyname,
List<Item> *key_expr, Item *cond);
#endif
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index fc218cb18f2..bd11397e2aa 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -92,10 +92,14 @@ static bool init_fields(THD *thd, TABLE_LIST *tables,
context->resolve_in_table_list_only(tables);
for (; count-- ; find_fields++)
{
+ LEX_CSTRING field_name= {find_fields->field_name,
+ strlen(find_fields->field_name) };
/* We have to use 'new' here as field will be re_linked on free */
- Item_field *field= new (thd->mem_root) Item_field(thd, context,
- "mysql", find_fields->table_name,
- find_fields->field_name);
+ Item_field *field= (new (thd->mem_root)
+ Item_field(thd, context,
+ "mysql",
+ find_fields->table_name,
+ &field_name));
if (!(find_fields->field= find_field_in_tables(thd, field, tables, NULL,
0, REPORT_ALL_ERRORS, 1,
TRUE)))
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index d037bad76ec..6e6a3228d80 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -289,7 +289,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (check_unique && thd->dup_field)
{
- my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dup_field->field_name);
+ my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0),
+ thd->dup_field->field_name.str);
DBUG_RETURN(-1);
}
}
@@ -328,7 +329,8 @@ static bool has_no_default_value(THD *thd, Field *field, TABLE_LIST *table_list)
else
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NO_DEFAULT_FOR_FIELD,
- ER_THD(thd, ER_NO_DEFAULT_FOR_FIELD), field->field_name);
+ ER_THD(thd, ER_NO_DEFAULT_FOR_FIELD),
+ field->field_name.str);
}
return thd->really_abort_on_warning();
}
@@ -4117,7 +4119,7 @@ static TABLE *create_table_from_items(THD *thd,
if (!mysql_create_table_no_lock(thd, create_table->db,
create_table->table_name,
create_info, alter_info, NULL,
- select_field_count))
+ select_field_count, create_table))
{
DEBUG_SYNC(thd,"create_table_select_before_open");
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 21d7637ec06..112ce36b1bf 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -30,6 +30,14 @@
#include "sp.h"
#include "sql_select.h"
#include "sql_cte.h"
+#include "sql_signal.h"
+
+
+void LEX::parse_error()
+{
+ thd->parse_error();
+}
+
static int lex_one_token(YYSTYPE *yylval, THD *thd);
@@ -43,8 +51,12 @@ sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
/**
LEX_STRING constant for null-string to be used in parser and other places.
*/
-const LEX_STRING null_lex_str= {NULL, 0};
-const LEX_STRING empty_lex_str= {(char *) "", 0};
+const LEX_STRING empty_lex_str= {(char *) "", 0};
+const LEX_CSTRING null_clex_str= {NULL, 0};
+const LEX_CSTRING empty_clex_str= {"", 0};
+const LEX_CSTRING star_clex_str= {"*", 1};
+const LEX_CSTRING param_clex_str= {"?", 1};
+
/**
@note The order of the elements of this array must correspond to
the order of elements in enum_binlog_stmt_unsafe.
@@ -184,8 +196,8 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
lex_start(thd);
context->init();
if ((!(table_ident= new Table_ident(thd,
- table->s->table_name,
- table->s->db, TRUE))) ||
+ &table->s->table_name,
+ &table->s->db, TRUE))) ||
(!(table_list= select_lex->add_table_to_list(thd,
table_ident,
NULL,
@@ -414,27 +426,28 @@ void Lex_input_stream::body_utf8_append(const char *ptr)
*/
void Lex_input_stream::body_utf8_append_ident(THD *thd,
- const LEX_STRING *txt,
+ const LEX_CSTRING *txt,
const char *end_ptr)
{
if (!m_cpp_utf8_processed_ptr)
return;
- LEX_STRING utf_txt;
+ LEX_CSTRING utf_txt;
CHARSET_INFO *txt_cs= thd->charset();
if (!my_charset_same(txt_cs, &my_charset_utf8_general_ci))
{
- thd->convert_string(&utf_txt,
+ LEX_STRING to;
+ thd->convert_string(&to,
&my_charset_utf8_general_ci,
txt->str, (uint) txt->length,
txt_cs);
+ utf_txt.str= to.str;
+ utf_txt.length= to.length;
+
}
else
- {
- utf_txt.str= txt->str;
- utf_txt.length= txt->length;
- }
+ utf_txt= *txt;
/* NOTE: utf_txt.length is in bytes, not in symbols. */
@@ -595,7 +608,7 @@ Lex_input_stream::get_escape_func(THD *thd, my_wc_t sep) const
@param sep - the string delimiter (single or double quote)
*/
void Lex_input_stream::body_utf8_append_escape(THD *thd,
- const LEX_STRING *txt,
+ const LEX_CSTRING *txt,
CHARSET_INFO *cs,
const char *end_ptr,
my_wc_t sep)
@@ -644,115 +657,122 @@ void Lex_input_stream::reduce_digest_token(uint token_left, uint token_right)
}
}
+void lex_start(THD *thd)
+{
+ DBUG_ENTER("lex_start");
+ thd->lex->start(thd);
+ DBUG_VOID_RETURN;
+}
+
+
/*
This is called before every query that is to be parsed.
Because of this, it's critical to not do too much things here.
(We already do too much here)
*/
-void lex_start(THD *thd)
+void LEX::start(THD *thd_arg)
{
- LEX *lex= thd->lex;
- DBUG_ENTER("lex_start");
+ DBUG_ENTER("LEX::start");
- lex->thd= lex->unit.thd= thd;
+ thd= unit.thd= thd_arg;
- DBUG_ASSERT(!lex->explain);
+ DBUG_ASSERT(!explain);
- lex->context_stack.empty();
- lex->unit.init_query();
- lex->unit.init_select();
+ context_stack.empty();
+ unit.init_query();
+ unit.init_select();
+ select_lex.linkage= UNSPECIFIED_TYPE;
/* 'parent_lex' is used in init_query() so it must be before it. */
- lex->select_lex.parent_lex= lex;
- lex->select_lex.init_query();
- lex->curr_with_clause= 0;
- lex->with_clauses_list= 0;
- lex->with_clauses_list_last_next= &lex->with_clauses_list;
- lex->value_list.empty();
- lex->update_list.empty();
- lex->set_var_list.empty();
- lex->param_list.empty();
- lex->view_list.empty();
- lex->with_column_list.empty();
- lex->with_persistent_for_clause= FALSE;
- lex->column_list= NULL;
- lex->index_list= NULL;
- lex->prepared_stmt_params.empty();
- lex->auxiliary_table_list.empty();
- lex->unit.next= lex->unit.master=
- lex->unit.link_next= lex->unit.return_to= 0;
- lex->unit.prev= lex->unit.link_prev= 0;
- lex->unit.slave= lex->current_select=
- lex->all_selects_list= &lex->select_lex;
- lex->select_lex.master= &lex->unit;
- lex->select_lex.prev= &lex->unit.slave;
- lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
- lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
- lex->select_lex.options= 0;
- lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
- lex->select_lex.init_order();
- lex->select_lex.group_list.empty();
- if (lex->select_lex.group_list_ptrs)
- lex->select_lex.group_list_ptrs->clear();
- lex->describe= 0;
- lex->analyze_stmt= 0;
- lex->explain_json= false;
- lex->subqueries= FALSE;
- lex->context_analysis_only= 0;
- lex->derived_tables= 0;
- lex->safe_to_cache_query= 1;
- lex->parsing_options.reset();
- lex->empty_field_list_on_rset= 0;
- lex->select_lex.select_number= 1;
- lex->part_info= 0;
- lex->select_lex.in_sum_expr=0;
- lex->select_lex.ftfunc_list_alloc.empty();
- lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
- lex->select_lex.group_list.empty();
- lex->select_lex.order_list.empty();
- lex->select_lex.gorder_list.empty();
- lex->m_sql_cmd= NULL;
- lex->duplicates= DUP_ERROR;
- lex->ignore= 0;
- lex->spname= NULL;
- lex->spcont= NULL;
- lex->proc_list.first= 0;
- lex->escape_used= FALSE;
- lex->query_tables= 0;
- lex->reset_query_tables_list(FALSE);
- lex->expr_allows_subselect= TRUE;
- lex->use_only_table_context= FALSE;
- lex->parse_vcol_expr= FALSE;
- lex->check_exists= FALSE;
- lex->create_info.lex_start();
- lex->verbose= 0;
-
- lex->name= null_lex_str;
- lex->event_parse_data= NULL;
- lex->profile_options= PROFILE_NONE;
- lex->nest_level=0 ;
- lex->select_lex.nest_level_base= &lex->unit;
- lex->allow_sum_func= 0;
- lex->in_sum_func= NULL;
-
- lex->used_tables= 0;
- lex->only_view= FALSE;
- lex->reset_slave_info.all= false;
- lex->limit_rows_examined= 0;
- lex->limit_rows_examined_cnt= ULONGLONG_MAX;
- lex->var_list.empty();
- lex->stmt_var_list.empty();
- lex->proc_list.elements=0;
-
- lex->save_group_list.empty();
- lex->save_order_list.empty();
- lex->win_ref= NULL;
- lex->win_frame= NULL;
- lex->frame_top_bound= NULL;
- lex->frame_bottom_bound= NULL;
- lex->win_spec= NULL;
-
- lex->is_lex_started= TRUE;
+ select_lex.parent_lex= this;
+ select_lex.init_query();
+ curr_with_clause= 0;
+ with_clauses_list= 0;
+ with_clauses_list_last_next= &with_clauses_list;
+ create_view= NULL;
+ value_list.empty();
+ update_list.empty();
+ set_var_list.empty();
+ param_list.empty();
+ view_list.empty();
+ with_column_list.empty();
+ with_persistent_for_clause= FALSE;
+ column_list= NULL;
+ index_list= NULL;
+ prepared_stmt_params.empty();
+ auxiliary_table_list.empty();
+ unit.next= unit.master= unit.link_next= unit.return_to= 0;
+ unit.prev= unit.link_prev= 0;
+ unit.slave= current_select= all_selects_list= &select_lex;
+ select_lex.master= &unit;
+ select_lex.prev= &unit.slave;
+ select_lex.link_next= select_lex.slave= select_lex.next= 0;
+ select_lex.link_prev= (st_select_lex_node**)&(all_selects_list);
+ select_lex.options= 0;
+ select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
+ select_lex.init_order();
+ select_lex.group_list.empty();
+ if (select_lex.group_list_ptrs)
+ select_lex.group_list_ptrs->clear();
+ describe= 0;
+ analyze_stmt= 0;
+ explain_json= false;
+ subqueries= FALSE;
+ context_analysis_only= 0;
+ derived_tables= 0;
+ safe_to_cache_query= 1;
+ parsing_options.reset();
+ empty_field_list_on_rset= 0;
+ select_lex.select_number= 1;
+ part_info= 0;
+ select_lex.in_sum_expr=0;
+ select_lex.ftfunc_list_alloc.empty();
+ select_lex.ftfunc_list= &select_lex.ftfunc_list_alloc;
+ select_lex.group_list.empty();
+ select_lex.order_list.empty();
+ select_lex.gorder_list.empty();
+ m_sql_cmd= NULL;
+ duplicates= DUP_ERROR;
+ ignore= 0;
+ spname= NULL;
+ spcont= NULL;
+ proc_list.first= 0;
+ escape_used= FALSE;
+ query_tables= 0;
+ reset_query_tables_list(FALSE);
+ expr_allows_subselect= TRUE;
+ use_only_table_context= FALSE;
+ parse_vcol_expr= FALSE;
+ check_exists= FALSE;
+ create_info.lex_start();
+ verbose= 0;
+
+ name= null_clex_str;
+ event_parse_data= NULL;
+ profile_options= PROFILE_NONE;
+ nest_level=0 ;
+ select_lex.nest_level_base= &unit;
+ allow_sum_func= 0;
+ in_sum_func= NULL;
+
+ used_tables= 0;
+ table_type= TABLE_TYPE_UNKNOWN;
+ reset_slave_info.all= false;
+ limit_rows_examined= 0;
+ limit_rows_examined_cnt= ULONGLONG_MAX;
+ var_list.empty();
+ stmt_var_list.empty();
+ proc_list.elements=0;
+
+ save_group_list.empty();
+ save_order_list.empty();
+ win_ref= NULL;
+ win_frame= NULL;
+ frame_top_bound= NULL;
+ frame_bottom_bound= NULL;
+ win_spec= NULL;
+
+ is_lex_started= TRUE;
DBUG_VOID_RETURN;
}
@@ -873,17 +893,70 @@ bool is_keyword(const char *name, uint len)
@retval 1 name isn't a function
*/
-bool is_lex_native_function(const LEX_STRING *name)
+bool is_lex_native_function(const LEX_CSTRING *name)
{
DBUG_ASSERT(name != NULL);
return (get_hash_symbol(name->str, (uint) name->length, 1) != 0);
}
+
+bool is_native_function(THD *thd, const LEX_CSTRING *name)
+{
+ if (find_native_function_builder(thd, name))
+ return true;
+
+ if (is_lex_native_function(name))
+ return true;
+
+ return false;
+}
+
+
+bool is_native_function_with_warn(THD *thd, const LEX_CSTRING *name)
+{
+ if (!is_native_function(thd, name))
+ return false;
+ /*
+ This warning will be printed when
+ [1] A client query is parsed,
+ [2] A stored function is loaded by db_load_routine.
+ Printing the warning for [2] is intentional, to cover the
+ following scenario:
+ - A user define a SF 'foo' using MySQL 5.N
+ - An application uses select foo(), and works.
+ - MySQL 5.{N+1} defines a new native function 'foo', as
+ part of a new feature.
+ - MySQL 5.{N+1} documentation is updated, and should mention
+ that there is a potential incompatible change in case of
+ existing stored function named 'foo'.
+ - The user deploys 5.{N+1}. At this point, 'select foo()'
+ means something different, and the user code is most likely
+ broken (it's only safe if the code is 'select db.foo()').
+ With a warning printed when the SF is loaded (which has to
+ occur before the call), the warning will provide a hint
+ explaining the root cause of a later failure of 'select foo()'.
+ With no warning printed, the user code will fail with no
+ apparent reason.
+ Printing a warning each time db_load_routine is executed for
+ an ambiguous function is annoying, since that can happen a lot,
+ but in practice should not happen unless there *are* name
+ collisions.
+ If a collision exists, it should not be silenced but fixed.
+ */
+ push_warning_printf(thd,
+ Sql_condition::WARN_LEVEL_NOTE,
+ ER_NATIVE_FCT_NAME_COLLISION,
+ ER_THD(thd, ER_NATIVE_FCT_NAME_COLLISION),
+ name->str);
+ return true;
+}
+
+
/* make a copy of token before ptr and set yytoklen */
-static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
+static LEX_CSTRING get_token(Lex_input_stream *lip, uint skip, uint length)
{
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
lip->yyUnget(); // ptr points now after last token char
tmp.length= length;
tmp.str= lip->m_thd->strmake(lip->get_tok_start() + skip, tmp.length);
@@ -901,18 +974,17 @@ static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
future to operate multichar strings (like ucs2)
*/
-static LEX_STRING get_quoted_token(Lex_input_stream *lip,
- uint skip,
- uint length, char quote)
+static LEX_CSTRING get_quoted_token(Lex_input_stream *lip,
+ uint skip,
+ uint length, char quote)
{
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
const char *from, *end;
char *to;
lip->yyUnget(); // ptr points now after last token char
tmp.length= length;
- tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
+ tmp.str= to= (char*) lip->m_thd->alloc(tmp.length+1);
from= lip->get_tok_start() + skip;
- to= tmp.str;
end= to+length;
lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
@@ -1002,18 +1074,19 @@ Lex_input_stream::unescape(CHARSET_INFO *cs, char *to,
Fix sometimes to do only one scan of the string
*/
-bool Lex_input_stream::get_text(LEX_STRING *dst, uint sep,
+bool Lex_input_stream::get_text(Lex_string_with_metadata_st *dst, uint sep,
int pre_skip, int post_skip)
{
reg1 uchar c;
uint found_escape=0;
CHARSET_INFO *cs= m_thd->charset();
- tok_bitmap= 0;
+ dst->set_8bit(false);
while (! eof())
{
c= yyGet();
- tok_bitmap|= c;
+ if (c & 0x80)
+ dst->set_8bit(true);
#ifdef USE_MB
{
int l;
@@ -1046,6 +1119,7 @@ bool Lex_input_stream::get_text(LEX_STRING *dst, uint sep,
/* Found end. Unescape and return string */
const char *str, *end;
+ char *to;
str= get_tok_start();
end= get_ptr();
@@ -1054,24 +1128,25 @@ bool Lex_input_stream::get_text(LEX_STRING *dst, uint sep,
end -= post_skip;
DBUG_ASSERT(end >= str);
- if (!(dst->str= (char*) m_thd->alloc((uint) (end - str) + 1)))
+ if (!(to= (char*) m_thd->alloc((uint) (end - str) + 1)))
{
- dst->str= (char*) ""; // Sql_alloc has set error flag
+ dst->str= ""; // Sql_alloc has set error flag
dst->length= 0;
return true;
}
+ dst->str= to;
m_cpp_text_start= get_cpp_tok_start() + pre_skip;
m_cpp_text_end= get_cpp_ptr() - post_skip;
if (!found_escape)
{
- memcpy(dst->str, str, dst->length= (end - str));
- dst->str[dst->length]= 0;
+ memcpy(to, str, dst->length= (end - str));
+ to[dst->length]= 0;
}
else
{
- dst->length= unescape(cs, dst->str, str, end, sep);
+ dst->length= unescape(cs, to, str, end, sep);
}
return false;
}
@@ -1281,6 +1356,11 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
return token;
}
+int ORAlex(YYSTYPE *yylval, THD *thd)
+{
+ return MYSQLlex(yylval, thd);
+}
+
static int lex_one_token(YYSTYPE *yylval, THD *thd)
{
reg1 uchar UNINIT_VAR(c);
@@ -1379,18 +1459,17 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
}
/* Found N'string' */
lip->yySkip(); // Skip '
- if (lip->get_text(&yylval->lex_str, (sep= lip->yyGetLast()), 2, 1))
+ if (lip->get_text(&yylval->lex_string_with_metadata,
+ (sep= lip->yyGetLast()), 2, 1))
{
state= MY_LEX_CHAR; // Read char by char
break;
}
lip->body_utf8_append(lip->m_cpp_text_start);
- lip->body_utf8_append_escape(thd, &yylval->lex_str,
+ lip->body_utf8_append_escape(thd, &yylval->lex_string_with_metadata,
national_charset_info,
lip->m_cpp_text_end, sep);
-
- lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1;
return(NCHAR_STRING);
}
case MY_LEX_IDENT_OR_HEX:
@@ -1641,8 +1720,13 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
return(IDENT_QUOTED);
}
case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
- if (c != '.')
- { // Found complete integer number.
+ if (c != '.' || lip->yyPeek() == '.')
+ {
+ /*
+ Found a complete integer number:
+ - the number is either not followed by a dot at all, or
+ - the number is followed by a double dot as in: FOR i IN 1..10
+ */
yylval->lex_str=get_token(lip, 0, lip->yyLength());
return int_token(yylval->lex_str.str, (uint) yylval->lex_str.length);
}
@@ -1747,7 +1831,8 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
case MY_LEX_STRING: // Incomplete text string
{
uint sep;
- if (lip->get_text(&yylval->lex_str, (sep= lip->yyGetLast()), 1, 1))
+ if (lip->get_text(&yylval->lex_string_with_metadata,
+ (sep= lip->yyGetLast()), 1, 1))
{
state= MY_LEX_CHAR; // Read char by char
break;
@@ -1755,11 +1840,9 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
CHARSET_INFO *strcs= lip->m_underscore_cs ? lip->m_underscore_cs : cs;
lip->body_utf8_append(lip->m_cpp_text_start);
- lip->body_utf8_append_escape(thd, &yylval->lex_str, strcs,
- lip->m_cpp_text_end, sep);
+ lip->body_utf8_append_escape(thd, &yylval->lex_string_with_metadata,
+ strcs, lip->m_cpp_text_end, sep);
lip->m_underscore_cs= NULL;
-
- lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1;
return(TEXT_STRING);
}
case MY_LEX_COMMENT: // Comment
@@ -1945,8 +2028,13 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
/* Actually real shouldn't start with . but allow them anyhow */
case MY_LEX_REAL_OR_POINT:
- if (my_isdigit(cs,lip->yyPeek()))
+ if (my_isdigit(cs,(c= lip->yyPeek())))
state = MY_LEX_REAL; // Real
+ else if (c == '.')
+ {
+ lip->yySkip();
+ return DOT_DOT_SYM;
+ }
else
{
state= MY_LEX_IDENT_SEP; // return '.'
@@ -2018,7 +2106,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
}
-void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str, uint *prefix_length)
+void trim_whitespace(CHARSET_INFO *cs, LEX_CSTRING *str, uint *prefix_length)
{
/*
TODO:
@@ -2085,6 +2173,7 @@ void st_select_lex_unit::init_query()
with_clause= 0;
with_element= 0;
columns_are_renamed= false;
+ intersect_mark= NULL;
}
void st_select_lex::init_query()
@@ -2159,7 +2248,6 @@ void st_select_lex::init_select()
ftfunc_list_alloc.empty();
inner_sum_func_list= 0;
ftfunc_list= &ftfunc_list_alloc;
- linkage= UNSPECIFIED_TYPE;
order_list.elements= 0;
order_list.first= 0;
order_list.next= &order_list.first;
@@ -2473,7 +2561,7 @@ uint st_select_lex_node::get_in_sum_expr() { return 0; }
TABLE_LIST* st_select_lex_node::get_table_list() { return 0; }
List<Item>* st_select_lex_node::get_item_list() { return 0; }
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
- LEX_STRING *alias,
+ LEX_CSTRING *alias,
ulong table_join_options,
thr_lock_type flags,
enum_mdl_type mdl_type,
@@ -2692,11 +2780,24 @@ void st_select_lex_unit::print(String *str, enum_query_type query_type)
{
if (sl != first_select())
{
- str->append(STRING_WITH_LEN(" union "));
- if (union_all)
- str->append(STRING_WITH_LEN("all "));
- else if (union_distinct == sl)
- union_all= TRUE;
+ switch (sl->linkage)
+ {
+ default:
+ DBUG_ASSERT(0);
+ case UNION_TYPE:
+ str->append(STRING_WITH_LEN(" union "));
+ if (union_all)
+ str->append(STRING_WITH_LEN("all "));
+ else if (union_distinct == sl)
+ union_all= TRUE;
+ break;
+ case INTERSECT_TYPE:
+ str->append(STRING_WITH_LEN(" intersect "));
+ break;
+ case EXCEPT_TYPE:
+ str->append(STRING_WITH_LEN(" except "));
+ break;
+ }
}
if (sl->braces)
str->append('(');
@@ -3135,7 +3236,7 @@ uint8 LEX::get_effective_with_check(TABLE_LIST *view)
*/
bool
-LEX::copy_db_to(char **p_db, size_t *p_db_length) const
+LEX::copy_db_to(const char **p_db, size_t *p_db_length) const
{
if (sphead && sphead->m_name.str)
{
@@ -3279,6 +3380,7 @@ void LEX::set_trg_event_type_for_tables()
REPLACE SELECT is handled later in this method.
*/
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
new_trg_event_map|= static_cast<uint8>
(1 << static_cast<int>(TRG_EVENT_INSERT));
break;
@@ -3717,7 +3819,7 @@ void st_select_lex::alloc_index_hints (THD *thd)
RETURN VALUE
0 on success, non-zero otherwise
*/
-bool st_select_lex::add_index_hint (THD *thd, char *str, uint length)
+bool st_select_lex::add_index_hint (THD *thd, const char *str, uint length)
{
return index_hints->push_front(new (thd->mem_root)
Index_hint(current_index_hint_type,
@@ -4231,7 +4333,8 @@ void SELECT_LEX::update_used_tables()
}
for (ORDER *order= group_list.first; order; order= order->next)
(*order->item)->update_used_tables();
- if (!master_unit()->is_union() || master_unit()->global_parameters() != this)
+ if (!master_unit()->is_unit_op() ||
+ master_unit()->global_parameters() != this)
{
for (ORDER *order= order_list.first; order; order= order->next)
(*order->item)->update_used_tables();
@@ -4289,7 +4392,7 @@ void st_select_lex::update_correlated_cache()
is_correlated|= MY_TEST((*order->item)->used_tables() &
OUTER_REF_TABLE_BIT);
- if (!master_unit()->is_union())
+ if (!master_unit()->is_unit_op())
{
for (ORDER *order= order_list.first; order; order= order->next)
is_correlated|= MY_TEST((*order->item)->used_tables() &
@@ -4377,36 +4480,47 @@ void st_select_lex::set_explain_type(bool on_the_fly)
}
else
{
- /* This a non-first sibling in UNION */
- if (is_uncacheable & UNCACHEABLE_DEPENDENT)
- type= "DEPENDENT UNION";
- else if (using_materialization)
- type= "MATERIALIZED UNION";
- else
+ switch (linkage)
{
- type= is_uncacheable ? "UNCACHEABLE UNION": "UNION";
- if (this == master_unit()->fake_select_lex)
- type= "UNION RESULT";
- /*
- join below may be =NULL when this functions is called at an early
- stage. It will be later called again and we will set the correct
- value.
- */
- if (join)
+ case INTERSECT_TYPE:
+ type= "INTERSECT";
+ break;
+ case EXCEPT_TYPE:
+ type= "EXCEPT";
+ break;
+ default:
+ /* This a non-first sibling in UNION */
+ if (is_uncacheable & UNCACHEABLE_DEPENDENT)
+ type= "DEPENDENT UNION";
+ else if (using_materialization)
+ type= "MATERIALIZED UNION";
+ else
{
- bool uses_cte= false;
- for (JOIN_TAB *tab= first_explain_order_tab(join); tab;
- tab= next_explain_order_tab(join, tab))
+ type= is_uncacheable ? "UNCACHEABLE UNION": "UNION";
+ if (this == master_unit()->fake_select_lex)
+ type= unit_operation_text[master_unit()->common_op()];
+ /*
+ join below may be =NULL when this functions is called at an early
+ stage. It will be later called again and we will set the correct
+ value.
+ */
+ if (join)
{
- if (tab->table && tab->table->pos_in_table_list->with)
+ bool uses_cte= false;
+ for (JOIN_TAB *tab= first_explain_order_tab(join); tab;
+ tab= next_explain_order_tab(join, tab))
{
- uses_cte= true;
- break;
+ if (tab->table && tab->table->pos_in_table_list->with)
+ {
+ uses_cte= true;
+ break;
+ }
}
+ if (uses_cte)
+ type= "RECURSIVE UNION";
}
- if (uses_cte)
- type= "RECURSIVE UNION";
}
+ break;
}
}
}
@@ -4445,8 +4559,20 @@ void SELECT_LEX::increase_derived_records(ha_rows records)
return;
}
- select_union *result= (select_union*)unit->result;
- result->records+= records;
+ select_unit *result= (select_unit*)unit->result;
+ switch (linkage)
+ {
+ case INTERSECT_TYPE:
+ // result of intersect can't be more then one of components
+ set_if_smaller(result->records, records);
+ case EXCEPT_TYPE:
+ // in worse case none of record will be removed
+ break;
+ default:
+ // usual UNION
+ result->records+= records;
+ break;
+ }
}
@@ -4471,7 +4597,7 @@ void SELECT_LEX::mark_const_derived(bool empty)
{
if (!empty)
increase_derived_records(1);
- if (!master_unit()->is_union() && !derived->is_merged_derived())
+ if (!master_unit()->is_unit_op() && !derived->is_merged_derived())
derived->fill_me= TRUE;
}
}
@@ -4700,6 +4826,42 @@ void LEX::restore_set_statement_var()
DBUG_VOID_RETURN;
}
+unit_common_op st_select_lex_unit::common_op()
+{
+ SELECT_LEX *first= first_select();
+ bool first_op= TRUE;
+ unit_common_op operation= OP_MIX; // if no op
+ for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
+ {
+ if (sl != first)
+ {
+ unit_common_op op;
+ switch (sl->linkage)
+ {
+ case INTERSECT_TYPE:
+ op= OP_INTERSECT;
+ break;
+ case EXCEPT_TYPE:
+ op= OP_EXCEPT;
+ break;
+ default:
+ op= OP_UNION;
+ break;
+ }
+ if (first_op)
+ {
+ operation= op;
+ first_op= FALSE;
+ }
+ else
+ {
+ if (operation != op)
+ operation= OP_MIX;
+ }
+ }
+ }
+ return operation;
+}
/*
Save explain structures of a UNION. The only variable member is whether the
union has "Using filesort".
@@ -4736,11 +4898,10 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
Note: Non-merged semi-joins cannot be made out of UNIONs currently, so we
dont ever set EXPLAIN_NODE_NON_MERGED_SJ.
*/
-
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
eu->add_select(sl->select_number);
- eu->fake_select_type= "UNION RESULT";
+ eu->fake_select_type= unit_operation_text[eu->operation= common_op()];
eu->using_filesort= MY_TEST(global_parameters()->order_list.first);
eu->using_tmp= union_needs_tmp_table();
@@ -4795,6 +4956,1742 @@ bool LEX::is_partition_management() const
alter_info.flags == Alter_info::ALTER_REORGANIZE_PARTITION));
}
+
+/**
+ Exclude last added SELECT_LEX (current) in the UNIT and return pointer in it
+ (previous become currect)
+
+ @return detached SELECT_LEX or NULL in case of error
+*/
+
+SELECT_LEX *LEX::exclude_last_select()
+{
+ DBUG_ENTER("SELECT_LEX::exclude_last_select");
+ SELECT_LEX *exclude= current_select;
+ SELECT_LEX_UNIT *unit= exclude->master_unit();
+ SELECT_LEX *sl;
+ DBUG_ASSERT(unit->first_select() != exclude);
+ /* we should go through the list to correctly set current_select */
+ for(sl= unit->first_select();
+ sl->next_select() && sl->next_select() != exclude;
+ sl= sl->next_select());
+ DBUG_PRINT("info", ("excl: %p unit: %p prev: %p", exclude, unit, sl));
+ if (!sl)
+ DBUG_RETURN(NULL);
+ DBUG_ASSERT(exclude->next_select() == NULL);
+ exclude->exclude_from_tree();
+ current_select= sl;
+ DBUG_RETURN(exclude);
+}
+
+
+/**
+ Put given (new) SELECT_LEX level below after currect (last) SELECT
+
+ LAST SELECT -> DUMMY SELECT
+ |
+ V
+ NEW UNIT
+ |
+ V
+ NEW SELECT
+
+ SELECT (*LAST*) ... FROM (SELECT (*NEW*) ... )
+
+ @param nselect Select to put one level below
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+
+bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
+{
+ DBUG_ENTER("LEX::add_unit_in_brackets");
+ bool distinct= nselect->master_unit()->union_distinct == nselect;
+ bool rc= add_select_to_union_list(distinct, nselect->linkage, 0);
+ if (rc)
+ DBUG_RETURN(TRUE);
+ SELECT_LEX* dummy_select= current_select;
+ dummy_select->automatic_brackets= TRUE;
+ dummy_select->linkage= nselect->linkage;
+
+ /* stuff dummy SELECT * FROM (...) */
+ Name_resolution_context *context= &dummy_select->context;
+ context->init();
+
+ /* add SELECT list*/
+ Item *item= new (thd->mem_root)
+ Item_field(thd, context, NULL, NULL, &star_clex_str);
+ if (item == NULL)
+ DBUG_RETURN(TRUE);
+ if (add_item_to_list(thd, item))
+ DBUG_RETURN(TRUE);
+ (dummy_select->with_wild)++;
+
+ rc= mysql_new_select(this, 1, nselect);
+ nselect->linkage= DERIVED_TABLE_TYPE;
+ DBUG_ASSERT(nselect->outer_select() == dummy_select);
+
+ current_select= dummy_select;
+ current_select->nest_level--;
+
+ SELECT_LEX_UNIT *unit= nselect->master_unit();
+ Table_ident *ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ DBUG_RETURN(TRUE);
+ char buff[10];
+ LEX_CSTRING alias;
+ alias.length= my_snprintf(buff, sizeof(buff),
+ "__%u", dummy_select->select_number);
+ alias.str= thd->strmake(buff, alias.length);
+ if (!alias.str)
+ DBUG_RETURN(TRUE);
+
+ TABLE_LIST *table_list;
+ if (!(table_list= dummy_select->add_table_to_list(thd, ti, &alias,
+ 0, TL_READ,
+ MDL_SHARED_READ)))
+ DBUG_RETURN(TRUE);
+ context->resolve_in_table_list_only(table_list);
+ dummy_select->add_joined_table(table_list);
+
+ derived_tables|= DERIVED_SUBQUERY;
+
+ current_select= nselect;
+ current_select->nest_level++;
+ DBUG_RETURN(rc);
+}
+
+
+/**
+ Checks if we need finish "automatic brackets" mode
+
+ INTERSECT has higher priority then UNION and EXCEPT, so when it is need we
+ automatically create lower layer for INTERSECT (automatic brackets) and
+ here we check if we should return back one level up during parsing procedure.
+*/
+
+void LEX::check_automatic_up(enum sub_select_type type)
+{
+ if (type != INTERSECT_TYPE &&
+ current_select->linkage == INTERSECT_TYPE &&
+ current_select->outer_select() &&
+ current_select->outer_select()->automatic_brackets)
+ {
+ nest_level--;
+ current_select= current_select->outer_select();
+ }
+}
+
+
+sp_variable *LEX::sp_param_init(LEX_CSTRING *name)
+{
+ if (spcont->find_variable(name, true))
+ {
+ my_error(ER_SP_DUP_PARAM, MYF(0), name->str);
+ return NULL;
+ }
+ sp_variable *spvar= spcont->add_variable(thd, name);
+ init_last_field(&spvar->field_def, name,
+ thd->variables.collation_database);
+ return spvar;
+}
+
+
+bool LEX::sp_param_fill_definition(sp_variable *spvar)
+{
+ return sphead->fill_spvar_definition(thd, last_field, &spvar->name);
+}
+
+
+void LEX::set_stmt_init()
+{
+ sql_command= SQLCOM_SET_OPTION;
+ mysql_init_select(this);
+ option_type= OPT_SESSION;
+ autocommit= 0;
+};
+
+
+bool LEX::init_internal_variable(struct sys_var_with_base *variable,
+ const LEX_CSTRING *name)
+{
+ sp_variable *spv;
+
+ /* Best effort lookup for system variable. */
+ if (!spcont || !(spv = spcont->find_variable(name, false)))
+ {
+ struct sys_var_with_base tmp= {NULL, *name};
+
+ /* Not an SP local variable */
+ if (find_sys_var_null_base(thd, &tmp))
+ return true;
+
+ *variable= tmp;
+ return false;
+ }
+
+ /*
+ Possibly an SP local variable (or a shadowed sysvar).
+ Will depend on the context of the SET statement.
+ */
+ variable->var= NULL;
+ variable->base_name= *name;
+ return false;
+}
+
+
+bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name)
+{
+ return sphead && sphead->m_type == TYPE_ENUM_TRIGGER &&
+ name->length == 3 &&
+ (!my_strcasecmp(system_charset_info, name->str, "NEW") ||
+ !my_strcasecmp(system_charset_info, name->str, "OLD"));
+}
+
+
+bool LEX::init_internal_variable(struct sys_var_with_base *variable,
+ const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name)
+{
+ if (check_reserved_words(dbname))
+ {
+ my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0),
+ (int) dbname->length, dbname->str);
+ return true;
+ }
+ if (is_trigger_new_or_old_reference(dbname))
+ {
+ if (dbname->str[0]=='O' || dbname->str[0]=='o')
+ {
+ my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
+ return true;
+ }
+ if (trg_chistics.event == TRG_EVENT_DELETE)
+ {
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
+ return true;
+ }
+ if (trg_chistics.action_time == TRG_ACTION_AFTER)
+ {
+ my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
+ return true;
+ }
+ /* This special combination will denote field of NEW row */
+ variable->var= trg_new_row_fake_var;
+ variable->base_name= *name;
+ return false;
+ }
+
+ sys_var *tmp= find_sys_var_ex(thd, name->str, name->length, true, false);
+ if (!tmp)
+ {
+ my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0),
+ (int) dbname->length, dbname->str);
+ return true;
+ }
+ if (!tmp->is_struct())
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name->str);
+ variable->var= tmp;
+ variable->base_name= *dbname;
+ return false;
+}
+
+
+bool LEX::init_default_internal_variable(struct sys_var_with_base *variable,
+ LEX_CSTRING name)
+{
+ sys_var *tmp= find_sys_var(thd, name.str, name.length);
+ if (!tmp)
+ return true;
+ if (!tmp->is_struct())
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name.str);
+ variable->var= tmp;
+ variable->base_name.str= (char*) "default";
+ variable->base_name.length= 7;
+ return false;
+}
+
+void LEX::sp_variable_declarations_init(THD *thd, int nvars)
+{
+ sp_variable *spvar= spcont->get_last_context_variable();
+
+ sphead->reset_lex(thd);
+ spcont->declare_var_boundary(nvars);
+ thd->lex->init_last_field(&spvar->field_def, &spvar->name,
+ thd->variables.collation_database);
+}
+
+bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
+ const Column_definition *cdef,
+ Row_definition_list *row,
+ Item *dflt_value_item)
+{
+ if (!dflt_value_item &&
+ !(dflt_value_item= new (thd->mem_root) Item_null(thd)))
+ return true;
+
+ /*
+ Prepare all row fields.
+ Note, we do it only one time outside of the below loop.
+ The converted list in "row" is further reused by all variable
+ declarations processed by the current call.
+ Example:
+ DECLARE
+ a, b, c ROW(x VARCHAR(10) CHARACTER SET utf8);
+ BEGIN
+ ...
+ END;
+ */
+ if (row && sphead->row_fill_field_definitions(thd, row))
+ return true;
+
+ for (uint i= 0 ; i < (uint) nvars ; i++)
+ {
+ sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+ bool last= i + 1 == (uint) nvars;
+
+ if (!spvar)
+ return true;
+
+ spvar->default_value= dflt_value_item;
+
+ if (cdef)
+ {
+ if (!last)
+ spvar->field_def.set_column_definition(cdef);
+ }
+ if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name))
+ return true;
+ spvar->field_def.set_row_field_definitions(row);
+
+ /* The last instruction is responsible for freeing LEX. */
+ sp_instr_set *is= new (this->thd->mem_root)
+ sp_instr_set(sphead->instructions(),
+ spcont, spvar->offset, dflt_value_item,
+ this, last);
+ if (is == NULL || sphead->add_instr(is))
+ return true;
+ }
+
+ spcont->declare_var_boundary(0);
+ return sphead->restore_lex(thd);
+}
+
+
+/**
+ Finalize a %ROWTYPE declaration, e.g.:
+ DECLARE a,b,c,d t1%ROWTYPE := ROW(1,2,3);
+
+ @param thd - the current thd
+ @param nvars - the number of variables in the declaration
+ @param ref - the table or cursor name (see comments below)
+ @param def - the default value, e.g., ROW(1,2,3), or NULL (no default).
+*/
+bool
+LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
+ Qualified_column_ident *ref,
+ Item *def)
+{
+ uint coffp;
+ const sp_pcursor *pcursor= ref->table.str && ref->db.str ? NULL :
+ spcont->find_cursor(&ref->m_column, &coffp,
+ false);
+
+ if (!def && !(def= new (thd->mem_root) Item_null(thd)))
+ return true;
+
+ // Loop through all variables in the same declaration
+ for (uint i= 0 ; i < (uint) nvars; i++)
+ {
+ bool last= i + 1 == (uint) nvars;
+ sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+
+ if (pcursor)
+ {
+ spvar->field_def.set_cursor_rowtype_ref(true);
+ sp_instr_cursor_copy_struct *instr=
+ new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
+ spcont, pcursor->lex(),
+ spvar->offset);
+ if (instr == NULL || sphead->add_instr(instr))
+ return true;
+ }
+ else
+ {
+ /*
+ When parsing a qualified identifier chain, the parser does not know yet
+ if it's going to be a qualified column name (for %TYPE),
+ or a qualified table name (for %ROWTYPE). So it collects the chain
+ into Qualified_column_ident.
+ Now we know that it was actually a qualified table name (%ROWTYPE).
+ Create a new Table_ident from Qualified_column_ident,
+ shifting fields as follows:
+ - ref->m_column becomes table_ref->table
+ - ref->table becomes table_ref->db
+ */
+ Table_ident *table_ref;
+ if (!(table_ref= new (thd->mem_root) Table_ident(thd,
+ &ref->table,
+ &ref->m_column,
+ false)))
+ return true;
+ spvar->field_def.set_table_rowtype_ref(table_ref);
+ }
+ sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
+ spvar->default_value= def;
+ /* The last instruction is responsible for freeing LEX. */
+ sp_instr_set *is= new (this->thd->mem_root)
+ sp_instr_set(sphead->instructions(),
+ spcont, spvar->offset, def,
+ this, last);
+ if (is == NULL || sphead->add_instr(is))
+ return true;
+ }
+ // Make sure sp_rcontext is created using the invoker security context:
+ sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
+ spcont->declare_var_boundary(0);
+ return sphead->restore_lex(thd);
+}
+
+
+bool
+LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
+ Qualified_column_ident *ref,
+ Item *def)
+{
+ for (uint i= 0 ; i < (uint) nvars; i++)
+ {
+ sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+ spvar->field_def.set_column_type_ref(ref);
+ spvar->field_def.field_name= spvar->name;
+ }
+ sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
+ return sp_variable_declarations_finalize(thd, nvars, NULL, NULL, def);
+}
+
+
+/**********************************************************************
+ The FOR LOOP statement
+
+ This syntax:
+ FOR i IN lower_bound .. upper_bound
+ LOOP
+ statements;
+ END LOOP;
+
+ is translated into:
+
+ DECLARE
+ i INT := lower_bound;
+ j INT := upper_bound;
+ BEGIN
+ WHILE i <= j
+ LOOP
+ statements;
+ i:= i + 1;
+ END LOOP;
+ END;
+*/
+
+
+sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
+ Item *value)
+{
+ sp_variable *spvar= spcont->add_variable(thd, name);
+ spcont->declare_var_boundary(1);
+ spvar->field_def.field_name= spvar->name;
+ spvar->field_def.set_handler(&type_handler_longlong);
+ type_handler_longlong.Column_definition_prepare_stage2(&spvar->field_def,
+ NULL, HA_CAN_GEOMETRY);
+ if (!value && !(value= new (thd->mem_root) Item_null(thd)))
+ return NULL;
+
+ spvar->default_value= value;
+ sp_instr_set *is= new (this->thd->mem_root)
+ sp_instr_set(sphead->instructions(),
+ spcont, spvar->offset, value,
+ this, true);
+ if (is == NULL || sphead->add_instr(is))
+ return NULL;
+ spcont->declare_var_boundary(0);
+ return spvar;
+}
+
+
+sp_variable *
+LEX::sp_add_for_loop_cursor_variable(THD *thd,
+ const LEX_CSTRING *name,
+ const sp_pcursor *pcursor,
+ uint coffset,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters)
+{
+ sp_variable *spvar= spcont->add_variable(thd, name);
+ if (!spvar)
+ return NULL;
+ spcont->declare_var_boundary(1);
+ sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
+ if (!(spvar->default_value= new (thd->mem_root) Item_null(thd)))
+ return NULL;
+
+ spvar->field_def.set_cursor_rowtype_ref(true);
+
+ if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset,
+ param_lex, parameters))
+ return NULL;
+
+ spcont->declare_var_boundary(0);
+ return spvar;
+}
+
+
+/**
+ Generate a code for a FOR loop condition:
+ - Make Item_splocal for the FOR loop index variable
+ - Make Item_splocal for the FOR loop upper bound variable
+ - Make a comparison function item on top of these two variables
+*/
+bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
+{
+ Item_splocal *args[2];
+ for (uint i= 0 ; i < 2; i++)
+ {
+ sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound;
+ args[i]= new (thd->mem_root)
+ Item_splocal(thd, &src->name, src->offset, src->sql_type());
+ if (args[i] == NULL)
+ return true;
+#ifndef DBUG_OFF
+ args[i]->m_sp= sphead;
+#endif
+ }
+
+ Item *expr= loop.m_direction > 0 ?
+ (Item *) new (thd->mem_root) Item_func_le(thd, args[0], args[1]) :
+ (Item *) new (thd->mem_root) Item_func_ge(thd, args[0], args[1]);
+ return !expr || sp_while_loop_expression(thd, expr);
+}
+
+
+/**
+ Generate the FOR LOOP condition code in its own lex
+*/
+bool LEX::sp_for_loop_intrange_condition_test(THD *thd,
+ const Lex_for_loop_st &loop)
+{
+ spcont->set_for_loop(loop);
+ sphead->reset_lex(thd);
+ if (thd->lex->sp_for_loop_condition(thd, loop))
+ return true;
+ return thd->lex->sphead->restore_lex(thd);
+}
+
+
+bool LEX::sp_for_loop_cursor_condition_test(THD *thd,
+ const Lex_for_loop_st &loop)
+{
+ const LEX_CSTRING *cursor_name;
+ Item *expr;
+ spcont->set_for_loop(loop);
+ sphead->reset_lex(thd);
+ cursor_name= spcont->find_cursor(loop.m_cursor_offset);
+ DBUG_ASSERT(cursor_name);
+ if (!(expr= new (thd->mem_root) Item_func_cursor_found(thd, cursor_name,
+ loop.m_cursor_offset)))
+ return true;
+ if (thd->lex->sp_while_loop_expression(thd, expr))
+ return true;
+ return thd->lex->sphead->restore_lex(thd);
+}
+
+
+bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
+ const LEX_CSTRING *index,
+ const Lex_for_loop_bounds_st &bounds)
+{
+ if (!(loop->m_index=
+ bounds.m_index->sp_add_for_loop_variable(thd, index,
+ bounds.m_index->get_item())))
+ return true;
+ if (!(loop->m_upper_bound=
+ bounds.m_upper_bound->sp_add_for_loop_upper_bound(thd,
+ bounds.m_upper_bound->get_item())))
+ return true;
+ loop->m_direction= bounds.m_direction;
+ loop->m_implicit_cursor= 0;
+ return false;
+}
+
+
+bool LEX::sp_for_loop_cursor_declarations(THD *thd,
+ Lex_for_loop_st *loop,
+ const LEX_CSTRING *index,
+ const Lex_for_loop_bounds_st &bounds)
+{
+ Item *item= bounds.m_index->get_item();
+ Item_splocal *item_splocal;
+ Item_field *item_field;
+ Item_func_sp *item_func_sp= NULL;
+ LEX_CSTRING name;
+ uint coffs, param_count= 0;
+ const sp_pcursor *pcursor;
+
+ if ((item_splocal= item->get_item_splocal()))
+ name= item_splocal->m_name;
+ else if ((item_field= item->type() == Item::FIELD_ITEM ?
+ static_cast<Item_field *>(item) : NULL) &&
+ item_field->table_name == NULL)
+ name= item_field->field_name;
+ else if (item->type() == Item::FUNC_ITEM &&
+ static_cast<Item_func*>(item)->functype() == Item_func::FUNC_SP &&
+ !static_cast<Item_func_sp*>(item)->get_sp_name()->m_explicit_name)
+ {
+ /*
+ When a FOR LOOP for a cursor with parameters is parsed:
+ FOR index IN cursor(1,2,3) LOOP
+ statements;
+ END LOOP;
+ the parser scans "cursor(1,2,3)" using the "expr" rule,
+ so it thinks that cursor(1,2,3) is a stored function call.
+ It's not easy to implement this without using "expr" because
+ of grammar conflicts.
+ As a side effect, the Item_func_sp and its arguments in the parentheses
+ belong to the same LEX. This is different from an explicit
+ "OPEN cursor(1,2,3)" where every expression belongs to a separate LEX.
+ */
+ item_func_sp= static_cast<Item_func_sp*>(item);
+ name= item_func_sp->get_sp_name()->m_name;
+ param_count= item_func_sp->argument_count();
+ }
+ else
+ {
+ thd->parse_error();
+ return true;
+ }
+ if (!(pcursor= spcont->find_cursor_with_error(&name, &coffs, false)) ||
+ pcursor->check_param_count_with_error(param_count))
+ return true;
+
+ if (!(loop->m_index= sp_add_for_loop_cursor_variable(thd, index,
+ pcursor, coffs,
+ bounds.m_index,
+ item_func_sp)))
+ return true;
+ loop->m_upper_bound= NULL;
+ loop->m_direction= bounds.m_direction;
+ loop->m_cursor_offset= coffs;
+ loop->m_implicit_cursor= bounds.m_implicit_cursor;
+ return false;
+}
+
+
+/**
+ Generate a code for a FOR loop index increment
+*/
+bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
+{
+ Item_splocal *splocal= new (thd->mem_root)
+ Item_splocal(thd, &loop.m_index->name, loop.m_index->offset,
+ loop.m_index->sql_type());
+ if (splocal == NULL)
+ return true;
+#ifndef DBUG_OFF
+ splocal->m_sp= sphead;
+#endif
+ Item_int *inc= new (thd->mem_root) Item_int(thd, loop.m_direction);
+ if (!inc)
+ return true;
+ Item *expr= new (thd->mem_root) Item_func_plus(thd, splocal, inc);
+ if (!expr ||
+ sphead->set_local_variable(thd, spcont, loop.m_index, expr, this, true))
+ return true;
+ return false;
+}
+
+
+bool LEX::sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop)
+{
+ sphead->reset_lex(thd);
+
+ // Generate FOR LOOP index increment in its own lex
+ DBUG_ASSERT(this != thd->lex);
+ if (thd->lex->sp_for_loop_increment(thd, loop) ||
+ thd->lex->sphead->restore_lex(thd))
+ return true;
+
+ // Generate a jump to the beginning of the loop
+ DBUG_ASSERT(this == thd->lex);
+ return sp_while_loop_finalize(thd);
+}
+
+
+bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop)
+{
+ sp_instr_cfetch *instr=
+ new (thd->mem_root) sp_instr_cfetch(sphead->instructions(),
+ spcont, loop.m_cursor_offset);
+ if (instr == NULL || sphead->add_instr(instr))
+ return true;
+ instr->add_to_varlist(loop.m_index);
+ // Generate a jump to the beginning of the loop
+ return sp_while_loop_finalize(thd);
+}
+
+/***************************************************************************/
+
+bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
+ sp_lex_cursor *cursor_stmt,
+ sp_pcontext *param_ctx, bool add_cpush_instr)
+{
+ uint offp;
+ sp_instr_cpush *i;
+
+ if (spcont->find_cursor(name, &offp, true))
+ {
+ my_error(ER_SP_DUP_CURS, MYF(0), name->str);
+ return true;
+ }
+ cursor_stmt->set_cursor_name(name);
+
+ if (spcont->add_cursor(name, param_ctx, cursor_stmt))
+ return true;
+
+ if (add_cpush_instr)
+ {
+ i= new (thd->mem_root)
+ sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt,
+ spcont->current_cursor_count() - 1);
+ return i == NULL || sphead->add_instr(i);
+ }
+ return false;
+}
+
+
+/**
+ Generate an SP code for an "OPEN cursor_name" statement.
+ @param thd
+ @param name - Name of the cursor
+ @param parameters - Cursor parameters, e.g. OPEN c(1,2,3)
+ @returns - false on success, true on error
+*/
+bool LEX::sp_open_cursor(THD *thd, const LEX_CSTRING *name,
+ List<sp_assignment_lex> *parameters)
+{
+ uint offset;
+ const sp_pcursor *pcursor;
+ uint param_count= parameters ? parameters->elements : 0;
+ return !(pcursor= spcont->find_cursor_with_error(name, &offset, false)) ||
+ pcursor->check_param_count_with_error(param_count) ||
+ sphead->add_open_cursor(thd, spcont, offset,
+ pcursor->param_context(), parameters);
+}
+
+
+bool LEX::sp_handler_declaration_init(THD *thd, int type)
+{
+ sp_handler *h= spcont->add_handler(thd, (sp_handler::enum_type) type);
+
+ spcont= spcont->push_context(thd, sp_pcontext::HANDLER_SCOPE);
+
+ sp_instr_hpush_jump *i=
+ new (thd->mem_root) sp_instr_hpush_jump(sphead->instructions(), spcont, h);
+
+ if (i == NULL || sphead->add_instr(i))
+ return true;
+
+ /* For continue handlers, mark end of handler scope. */
+ if (type == sp_handler::CONTINUE &&
+ sphead->push_backpatch(thd, i, spcont->last_label()))
+ return true;
+
+ if (sphead->push_backpatch(thd, i, spcont->push_label(thd, &empty_clex_str, 0)))
+ return true;
+
+ return false;
+}
+
+
+bool LEX::sp_handler_declaration_finalize(THD *thd, int type)
+{
+ sp_label *hlab= spcont->pop_label(); /* After this hdlr */
+ sp_instr_hreturn *i;
+
+ if (type == sp_handler::CONTINUE)
+ {
+ i= new (thd->mem_root) sp_instr_hreturn(sphead->instructions(), spcont);
+ if (i == NULL ||
+ sphead->add_instr(i))
+ return true;
+ }
+ else
+ { /* EXIT or UNDO handler, just jump to the end of the block */
+ i= new (thd->mem_root) sp_instr_hreturn(sphead->instructions(), spcont);
+ if (i == NULL ||
+ sphead->add_instr(i) ||
+ sphead->push_backpatch(thd, i, spcont->last_label())) /* Block end */
+ return true;
+ }
+ sphead->backpatch(hlab);
+ spcont= spcont->pop_context();
+ return false;
+}
+
+
+void LEX::sp_block_init(THD *thd, const LEX_CSTRING *label)
+{
+ spcont->push_label(thd, label, sphead->instructions(), sp_label::BEGIN);
+ spcont= spcont->push_context(thd, sp_pcontext::REGULAR_SCOPE);
+}
+
+
+bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
+ class sp_label **splabel)
+{
+ sp_head *sp= sphead;
+ sp_pcontext *ctx= spcont;
+ sp_instr *i;
+
+ sp->backpatch(ctx->last_label()); /* We always have a label */
+ if (spblock.hndlrs)
+ {
+ i= new (thd->mem_root)
+ sp_instr_hpop(sp->instructions(), ctx, spblock.hndlrs);
+ if (i == NULL ||
+ sp->add_instr(i))
+ return true;
+ }
+ if (spblock.curs)
+ {
+ i= new (thd->mem_root)
+ sp_instr_cpop(sp->instructions(), ctx, spblock.curs);
+ if (i == NULL ||
+ sp->add_instr(i))
+ return true;
+ }
+ spcont= ctx->pop_context();
+ *splabel= spcont->pop_label();
+ return false;
+}
+
+
+bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
+ const LEX_CSTRING *end_label)
+{
+ sp_label *splabel;
+ if (sp_block_finalize(thd, spblock, &splabel))
+ return true;
+ if (end_label->str &&
+ my_strcasecmp(system_charset_info,
+ end_label->str, splabel->name.str) != 0)
+ {
+ my_error(ER_SP_LABEL_MISMATCH, MYF(0), end_label->str);
+ return true;
+ }
+ return false;
+}
+
+
+sp_name *LEX::make_sp_name(THD *thd, LEX_CSTRING *name)
+{
+ sp_name *res;
+ LEX_CSTRING db;
+ if (check_routine_name(name) ||
+ copy_db_to(&db.str, &db.length) ||
+ (!(res= new (thd->mem_root) sp_name(&db, name, false))))
+ return NULL;
+ return res;
+}
+
+
+sp_name *LEX::make_sp_name(THD *thd, LEX_CSTRING *name1, LEX_CSTRING *name2)
+{
+ sp_name *res;
+ if (!name1->str || check_db_name((LEX_STRING*) name1))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), name1->str);
+ return NULL;
+ }
+ if (check_routine_name(name2) ||
+ (!(res= new (thd->mem_root) sp_name(name1, name2, true))))
+ return NULL;
+ return res;
+}
+
+
+sp_head *LEX::make_sp_head(THD *thd, sp_name *name,
+ enum stored_procedure_type type)
+{
+ sp_head *sp;
+
+ /* Order is important here: new - reset - init */
+ if ((sp= new sp_head(type)))
+ {
+ sp->reset_thd_mem_root(thd);
+ sp->init(this);
+ if (name)
+ sp->init_sp_name(thd, name);
+ sphead= sp;
+ }
+ sp_chistics.init();
+ return sp;
+}
+
+
+bool LEX::sp_block_with_exceptions_finalize_declarations(THD *thd)
+{
+ /*
+ [ DECLARE declarations ]
+ BEGIN executable_section
+ [ EXCEPTION exceptions ]
+ END
+
+ We are now at the "BEGIN" keyword.
+ We have collected all declarations, including DECLARE HANDLER directives.
+ But there will be possibly more handlers in the EXCEPTION section.
+
+ Generate a forward jump from the end of the DECLARE section to the
+ beginning of the EXCEPTION section, over the executable section.
+ */
+ return sphead->add_instr_jump(thd, spcont);
+}
+
+
+bool
+LEX::sp_block_with_exceptions_finalize_executable_section(THD *thd,
+ uint executable_section_ip)
+{
+ /*
+ We're now at the end of "executable_section" of the block,
+ near the "EXCEPTION" or the "END" keyword.
+ Generate a jump to the END of the block over the EXCEPTION section.
+ */
+ if (sphead->add_instr_jump_forward_with_backpatch(thd, spcont))
+ return true;
+ /*
+ Set the destination for the jump that we added in
+ sp_block_with_exceptions_finalize_declarations().
+ */
+ sp_instr *instr= sphead->get_instr(executable_section_ip - 1);
+ instr->backpatch(sphead->instructions(), spcont);
+ return false;
+}
+
+
+bool
+LEX::sp_block_with_exceptions_finalize_exceptions(THD *thd,
+ uint executable_section_ip,
+ uint exception_count)
+{
+ if (!exception_count)
+ {
+ /*
+ The jump from the end of DECLARE section to
+ the beginning of the EXCEPTION section that we added in
+ sp_block_with_exceptions_finalize_declarations() is useless
+ if there were no exceptions.
+ Replace it to "no operation".
+ */
+ return sphead->replace_instr_to_nop(thd, executable_section_ip - 1);
+ }
+ /*
+ Generate a jump from the end of the EXCEPTION code
+ to the executable section.
+ */
+ return sphead->add_instr_jump(thd, spcont, executable_section_ip);
+}
+
+
+bool LEX::sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive)
+{
+ uint n;
+ uint ip= sphead->instructions();
+ if ((n= spcont->diff_handlers(ctx, exclusive)))
+ {
+ sp_instr_hpop *hpop= new (thd->mem_root) sp_instr_hpop(ip++, spcont, n);
+ if (hpop == NULL || sphead->add_instr(hpop))
+ return true;
+ }
+ if ((n= spcont->diff_cursors(ctx, exclusive)))
+ {
+ sp_instr_cpop *cpop= new (thd->mem_root) sp_instr_cpop(ip++, spcont, n);
+ if (cpop == NULL || sphead->add_instr(cpop))
+ return true;
+ }
+ return false;
+}
+
+
+bool LEX::sp_leave_statement(THD *thd, const LEX_CSTRING *label_name)
+{
+ sp_label *lab= spcont->find_label(label_name);
+ if (!lab)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name->str);
+ return true;
+ }
+ return sp_exit_block(thd, lab, NULL);
+}
+
+bool LEX::sp_goto_statement(THD *thd, const LEX_CSTRING *label_name)
+{
+ sp_label *lab= spcont->find_goto_label(label_name);
+ if (!lab || lab->ip == 0)
+ {
+ sp_label *delayedlabel;
+ if (!lab)
+ {
+ // Label not found --> add forward jump to an unknown label
+ spcont->push_goto_label(thd, label_name, 0, sp_label::GOTO);
+ delayedlabel= spcont->last_goto_label();
+ }
+ else
+ {
+ delayedlabel= lab;
+ }
+ return sphead->push_backpatch_goto(thd, spcont, delayedlabel);
+ }
+ else
+ {
+ // Label found (backward goto)
+ return sp_change_context(thd, lab->ctx, false) ||
+ sphead->add_instr_jump(thd, spcont, lab->ip); /* Jump back */
+ }
+ return false;
+}
+
+bool LEX::sp_push_goto_label(THD *thd, const LEX_CSTRING *label_name)
+{
+ sp_label *lab= spcont->find_goto_label(label_name, false);
+ if (lab)
+ {
+ if (lab->ip != 0)
+ {
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), label_name->str);
+ return true;
+ }
+ lab->ip= sphead->instructions();
+
+ sp_label *beginblocklabel= spcont->find_label(&empty_clex_str);
+ sphead->backpatch_goto(thd, lab, beginblocklabel);
+ }
+ else
+ {
+ spcont->push_goto_label(thd, label_name, sphead->instructions());
+ }
+ return false;
+}
+
+bool LEX::sp_exit_block(THD *thd, sp_label *lab)
+{
+ /*
+ When jumping to a BEGIN-END block end, the target jump
+ points to the block hpop/cpop cleanup instructions,
+ so we should exclude the block context here.
+ When jumping to something else (i.e., SP_LAB_ITER),
+ there are no hpop/cpop at the jump destination,
+ so we should include the block context here for cleanup.
+ */
+ bool exclusive= (lab->type == sp_label::BEGIN);
+ return sp_change_context(thd, lab->ctx, exclusive) ||
+ sphead->add_instr_jump_forward_with_backpatch(thd, spcont, lab);
+}
+
+
+bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
+{
+ if (!when)
+ return sp_exit_block(thd, lab);
+
+ DBUG_ASSERT(sphead == thd->lex->sphead);
+ DBUG_ASSERT(spcont == thd->lex->spcont);
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(sphead->instructions(),
+ spcont,
+ when, thd->lex);
+ if (i == NULL ||
+ sphead->add_instr(i) ||
+ sp_exit_block(thd, lab))
+ return true;
+ i->backpatch(sphead->instructions(), spcont);
+ return false;
+}
+
+
+bool LEX::sp_exit_statement(THD *thd, Item *item)
+{
+ sp_label *lab= spcont->find_label_current_loop_start();
+ if (!lab)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", "");
+ return true;
+ }
+ DBUG_ASSERT(lab->type == sp_label::ITERATION);
+ return sp_exit_block(thd, lab, item);
+}
+
+
+bool LEX::sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item)
+{
+ sp_label *lab= spcont->find_label(label_name);
+ if (!lab || lab->type != sp_label::ITERATION)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", label_name->str);
+ return true;
+ }
+ return sp_exit_block(thd, lab, item);
+}
+
+
+bool LEX::sp_iterate_statement(THD *thd, const LEX_CSTRING *label_name)
+{
+ sp_label *lab= spcont->find_label(label_name);
+ if (!lab || lab->type != sp_label::ITERATION)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", label_name->str);
+ return true;
+ }
+ return sp_continue_loop(thd, lab);
+}
+
+
+bool LEX::sp_continue_loop(THD *thd, sp_label *lab)
+{
+ if (lab->ctx->for_loop().m_index)
+ {
+ // We're in a FOR loop, increment the index variable before backward jump
+ sphead->reset_lex(thd);
+ DBUG_ASSERT(this != thd->lex);
+ if (thd->lex->sp_for_loop_increment(thd, lab->ctx->for_loop()) ||
+ thd->lex->sphead->restore_lex(thd))
+ return true;
+ }
+ return sp_change_context(thd, lab->ctx, false) ||
+ sphead->add_instr_jump(thd, spcont, lab->ip); /* Jump back */
+}
+
+
+bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
+{
+ if (!when)
+ return sp_continue_loop(thd, lab);
+
+ DBUG_ASSERT(sphead == thd->lex->sphead);
+ DBUG_ASSERT(spcont == thd->lex->spcont);
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(sphead->instructions(),
+ spcont,
+ when, thd->lex);
+ if (i == NULL ||
+ sphead->add_instr(i) ||
+ sp_continue_loop(thd, lab))
+ return true;
+ i->backpatch(sphead->instructions(), spcont);
+ return false;
+}
+
+
+bool LEX::sp_continue_statement(THD *thd, Item *when)
+{
+ sp_label *lab= spcont->find_label_current_loop_start();
+ if (!lab)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "CONTINUE", "");
+ return true;
+ }
+ DBUG_ASSERT(lab->type == sp_label::ITERATION);
+ return sp_continue_loop(thd, lab, when);
+}
+
+
+bool LEX::sp_continue_statement(THD *thd, const LEX_CSTRING *label_name,
+ Item *when)
+{
+ sp_label *lab= spcont->find_label(label_name);
+ if (!lab || lab->type != sp_label::ITERATION)
+ {
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "CONTINUE", label_name->str);
+ return true;
+ }
+ return sp_continue_loop(thd, lab, when);
+}
+
+
+bool LEX::maybe_start_compound_statement(THD *thd)
+{
+ if (!sphead)
+ {
+ if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
+ return true;
+ sphead->set_suid(SP_IS_NOT_SUID);
+ sphead->set_body_start(thd, thd->m_parser_state->m_lip.get_cpp_ptr());
+ }
+ return false;
+}
+
+
+bool LEX::sp_push_loop_label(THD *thd, const LEX_CSTRING *label_name)
+{
+ sp_label *lab= spcont->find_label(label_name);
+ if (lab)
+ {
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), label_name->str);
+ return true;
+ }
+ spcont->push_label(thd, label_name, sphead->instructions(),
+ sp_label::ITERATION);
+ return false;
+}
+
+
+bool LEX::sp_push_loop_empty_label(THD *thd)
+{
+ if (maybe_start_compound_statement(thd))
+ return true;
+ /* Unlabeled controls get an empty label. */
+ spcont->push_label(thd, &empty_clex_str, sphead->instructions(),
+ sp_label::ITERATION);
+ return false;
+}
+
+
+bool LEX::sp_pop_loop_label(THD *thd, const LEX_CSTRING *label_name)
+{
+ sp_label *lab= spcont->pop_label();
+ sphead->backpatch(lab);
+ if (label_name->str &&
+ my_strcasecmp(system_charset_info, label_name->str,
+ lab->name.str) != 0)
+ {
+ my_error(ER_SP_LABEL_MISMATCH, MYF(0), label_name->str);
+ return true;
+ }
+ return false;
+}
+
+
+void LEX::sp_pop_loop_empty_label(THD *thd)
+{
+ sp_label *lab= spcont->pop_label();
+ sphead->backpatch(lab);
+ DBUG_ASSERT(lab->name.length == 0);
+}
+
+
+bool LEX::sp_while_loop_expression(THD *thd, Item *expr)
+{
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(sphead->instructions(), spcont, expr, this);
+ return i == NULL ||
+ /* Jumping forward */
+ sphead->push_backpatch(thd, i, spcont->last_label()) ||
+ sphead->new_cont_backpatch(i) ||
+ sphead->add_instr(i);
+}
+
+
+bool LEX::sp_while_loop_finalize(THD *thd)
+{
+ sp_label *lab= spcont->last_label(); /* Jumping back */
+ sp_instr_jump *i= new (thd->mem_root)
+ sp_instr_jump(sphead->instructions(), spcont, lab->ip);
+ if (i == NULL ||
+ sphead->add_instr(i))
+ return true;
+ sphead->do_cont_backpatch();
+ return false;
+}
+
+
+Item *LEX::create_and_link_Item_trigger_field(THD *thd,
+ const LEX_CSTRING *name,
+ bool new_row)
+{
+ Item_trigger_field *trg_fld;
+
+ if (trg_chistics.event == TRG_EVENT_INSERT && !new_row)
+ {
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
+ return NULL;
+ }
+
+ if (trg_chistics.event == TRG_EVENT_DELETE && new_row)
+ {
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
+ return NULL;
+ }
+
+ DBUG_ASSERT(!new_row ||
+ (trg_chistics.event == TRG_EVENT_INSERT ||
+ trg_chistics.event == TRG_EVENT_UPDATE));
+
+ const bool tmp_read_only=
+ !(new_row && trg_chistics.action_time == TRG_ACTION_BEFORE);
+ trg_fld= new (thd->mem_root)
+ Item_trigger_field(thd, current_context(),
+ new_row ?
+ Item_trigger_field::NEW_ROW:
+ Item_trigger_field::OLD_ROW,
+ name, SELECT_ACL, tmp_read_only);
+ /*
+ Let us add this item to list of all Item_trigger_field objects
+ in trigger.
+ */
+ if (trg_fld)
+ trg_table_fields.link_in_list(trg_fld, &trg_fld->next_trg_field);
+
+ return trg_fld;
+}
+
+
+Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
+ uint pos_in_query, uint len_in_query)
+{
+ if (!parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ return NULL;
+ }
+ Item_param *item= new (thd->mem_root) Item_param(thd, name,
+ pos_in_query, len_in_query);
+ if (!item || param_list.push_back(item, thd->mem_root))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return NULL;
+ }
+ return item;
+}
+
+
+const char *LEX::substatement_query(THD *thd) const
+{
+ return sphead ? sphead->m_tmp_query : thd->query();
+}
+
+
+bool LEX::add_signal_statement(THD *thd, const sp_condition_value *v)
+{
+ Yacc_state *state= &thd->m_parser_state->m_yacc;
+ sql_command= SQLCOM_SIGNAL;
+ m_sql_cmd= new (thd->mem_root) Sql_cmd_signal(v, state->m_set_signal_info);
+ return m_sql_cmd == NULL;
+}
+
+
+bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v)
+{
+ Yacc_state *state= &thd->m_parser_state->m_yacc;
+ sql_command= SQLCOM_RESIGNAL;
+ m_sql_cmd= new (thd->mem_root) Sql_cmd_resignal(v, state->m_set_signal_info);
+ return m_sql_cmd == NULL;
+}
+
+
+Item *LEX::create_item_ident_nospvar(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b)
+{
+ DBUG_ASSERT(this == thd->lex);
+ /*
+ FIXME This will work ok in simple_ident_nospvar case because
+ we can't meet simple_ident_nospvar in trigger now. But it
+ should be changed in future.
+ */
+ if (is_trigger_new_or_old_reference(a))
+ {
+ bool new_row= (a->str[0]=='N' || a->str[0]=='n');
+
+ return create_and_link_Item_trigger_field(thd, b, new_row);
+ }
+
+ if (current_select->no_table_names_allowed)
+ {
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), a->str, thd->where);
+ return NULL;
+ }
+ if ((current_select->parsing_place != IN_HAVING) ||
+ (current_select->get_in_sum_expr() > 0))
+ return new (thd->mem_root) Item_field(thd, current_context(),
+ NullS, a->str, b);
+ return new (thd->mem_root) Item_ref(thd, current_context(),
+ NullS, a->str, b);
+}
+
+
+Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ sp_variable *spv,
+ uint pos_in_q,
+ uint length_in_q)
+{
+ if (!parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ return NULL;
+ }
+
+ Item_splocal *item;
+ if (spv->field_def.is_table_rowtype_ref() ||
+ spv->field_def.is_cursor_rowtype_ref())
+ {
+ if (!(item= new (thd->mem_root)
+ Item_splocal_row_field_by_name(thd, a, b, spv->offset,
+ MYSQL_TYPE_NULL,
+ pos_in_q, length_in_q)))
+ return NULL;
+ }
+ else
+ {
+ uint row_field_offset;
+ const Spvar_definition *def;
+ if (!(def= spv->find_row_field(a, b, &row_field_offset)))
+ return NULL;
+
+ if (!(item= new (thd->mem_root)
+ Item_splocal_row_field(thd, a, b,
+ spv->offset, row_field_offset,
+ def->real_field_type(),
+ pos_in_q, length_in_q)))
+ return NULL;
+ }
+#ifndef DBUG_OFF
+ item->m_sp= sphead;
+#endif
+ safe_to_cache_query=0;
+ return item;
+}
+
+
+my_var *LEX::create_outvar(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b)
+{
+ sp_variable *t;
+ if (!spcont || !(t= spcont->find_variable(a, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), a->str);
+ return NULL;
+ }
+ uint row_field_offset;
+ if (!t->find_row_field(a, b, &row_field_offset))
+ return NULL;
+ return result ?
+ new (thd->mem_root) my_var_sp_row_field(a, b, t->offset,
+ row_field_offset, sphead) :
+ NULL;
+}
+
+
+Item *LEX::create_item_func_nextval(THD *thd, Table_ident *table_ident)
+{
+ TABLE_LIST *table;
+ if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE_ALLOW_WRITE,
+ MDL_SHARED_WRITE)))
+ return NULL;
+ return new (thd->mem_root) Item_func_nextval(thd, table);
+}
+
+
+Item *LEX::create_item_func_lastval(THD *thd, Table_ident *table_ident)
+{
+ TABLE_LIST *table;
+ if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
+ TL_OPTION_SEQUENCE,
+ TL_READ,
+ MDL_SHARED_READ)))
+ return NULL;
+ return new (thd->mem_root) Item_func_lastval(thd, table);
+}
+
+
+Item *LEX::create_item_func_nextval(THD *thd,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *name)
+{
+ Table_ident *table_ident;
+ if (!(table_ident= new (thd->mem_root) Table_ident(thd, db, name, false)))
+ return NULL;
+ return create_item_func_nextval(thd, table_ident);
+}
+
+
+Item *LEX::create_item_func_lastval(THD *thd,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *name)
+{
+ Table_ident *table_ident;
+ if (!(table_ident= new (thd->mem_root) Table_ident(thd, db, name, false)))
+ return NULL;
+ return create_item_func_lastval(thd, table_ident);
+}
+
+
+Item *LEX::create_item_func_setval(THD *thd, Table_ident *table_ident,
+ longlong nextval, ulonglong round,
+ bool is_used)
+{
+ TABLE_LIST *table;
+ if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE_ALLOW_WRITE,
+ MDL_SHARED_WRITE)))
+ return NULL;
+ return new (thd->mem_root) Item_func_setval(thd, table, nextval, round,
+ is_used);
+}
+
+
+Item *LEX::create_item_ident(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ uint pos_in_q, uint length_in_q)
+{
+ sp_variable *spv;
+ if (spcont && (spv= spcont->find_variable(a, false)) &&
+ (spv->field_def.is_row() ||
+ spv->field_def.is_table_rowtype_ref() ||
+ spv->field_def.is_cursor_rowtype_ref()))
+ return create_item_spvar_row_field(thd, a, b, spv, pos_in_q, length_in_q);
+
+ if ((thd->variables.sql_mode & MODE_ORACLE) && b->length == 7)
+ {
+ if (!my_strnncoll(system_charset_info,
+ (const uchar *) b->str, 7,
+ (const uchar *) "NEXTVAL", 7))
+ return create_item_func_nextval(thd, &null_clex_str, a);
+ else if (!my_strnncoll(system_charset_info,
+ (const uchar *) b->str, 7,
+ (const uchar *) "CURRVAL", 7))
+ return create_item_func_lastval(thd, &null_clex_str, a);
+ }
+
+ return create_item_ident_nospvar(thd, a, b);
+}
+
+
+Item *LEX::create_item_ident(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ const LEX_CSTRING *c)
+{
+ const char *schema= (thd->client_capabilities & CLIENT_NO_SCHEMA ?
+ NullS : a->str);
+
+ if ((thd->variables.sql_mode & MODE_ORACLE) && c->length == 7)
+ {
+ if (!my_strnncoll(system_charset_info,
+ (const uchar *) c->str, 7,
+ (const uchar *) "NEXTVAL", 7))
+ return create_item_func_nextval(thd, a, b);
+ else if (!my_strnncoll(system_charset_info,
+ (const uchar *) c->str, 7,
+ (const uchar *) "CURRVAL", 7))
+ return create_item_func_lastval(thd, a, b);
+ }
+
+ if (current_select->no_table_names_allowed)
+ {
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), b->str, thd->where);
+ return NULL;
+ }
+ if (current_select->parsing_place != IN_HAVING ||
+ current_select->get_in_sum_expr() > 0)
+ return new (thd->mem_root) Item_field(thd, current_context(),
+ schema, b->str, c);
+ return new (thd->mem_root) Item_ref(thd, current_context(),
+ schema, b->str, c);
+}
+
+
+Item *LEX::create_item_limit(THD *thd,
+ const LEX_CSTRING *a,
+ uint pos_in_q, uint length_in_q)
+{
+ sp_variable *spv;
+ if (!spcont || !(spv= spcont->find_variable(a, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), a->str);
+ return NULL;
+ }
+
+ Item_splocal *item;
+ if (!(item= new (thd->mem_root) Item_splocal(thd, a,
+ spv->offset, spv->sql_type(),
+ pos_in_q, length_in_q)))
+ return NULL;
+#ifndef DBUG_OFF
+ item->m_sp= sphead;
+#endif
+ safe_to_cache_query= 0;
+
+ if (item->type() != Item::INT_ITEM)
+ {
+ my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ return NULL;
+ }
+ item->limit_clause_param= true;
+ return item;
+}
+
+
+Item *LEX::create_item_limit(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ uint pos_in_q, uint length_in_q)
+{
+ sp_variable *spv;
+ if (!spcont || !(spv= spcont->find_variable(a, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), a->str);
+ return NULL;
+ }
+ // Qualified %TYPE variables are not possible
+ DBUG_ASSERT(!spv->field_def.column_type_ref());
+ Item_splocal *item;
+ if (!(item= create_item_spvar_row_field(thd, a, b, spv,
+ pos_in_q, length_in_q)))
+ return NULL;
+ if (item->type() != Item::INT_ITEM)
+ {
+ my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ return NULL;
+ }
+ item->limit_clause_param= true;
+ return item;
+}
+
+
+/*
+ Perform assignment for a trigger, a system variable, or an SP variable.
+ "variable" be previously set by init_internal_variable(variable, name).
+*/
+bool LEX::set_variable(struct sys_var_with_base *variable, Item *item)
+{
+ if (variable->var == trg_new_row_fake_var)
+ {
+ /* We are in trigger and assigning value to field of new row */
+ return set_trigger_new_row(&variable->base_name, item);
+ }
+ if (variable->var)
+ {
+ /* It is a system variable. */
+ return set_system_variable(variable, option_type, item);
+ }
+
+ /*
+ spcont and spv should not be NULL, as the variable
+ was previously checked by init_internal_variable().
+ */
+ DBUG_ASSERT(spcont);
+ sp_variable *spv= spcont->find_variable(&variable->base_name, false);
+ DBUG_ASSERT(spv);
+ /* It is a local variable. */
+ return sphead->set_local_variable(thd, spcont, spv, item, this, true);
+}
+
+
+Item *LEX::create_item_ident_nosp(THD *thd, LEX_CSTRING *name)
+{
+ if (current_select->parsing_place != IN_HAVING ||
+ current_select->get_in_sum_expr() > 0)
+ return new (thd->mem_root) Item_field(thd, current_context(),
+ NullS, NullS, name);
+
+ return new (thd->mem_root) Item_ref(thd, current_context(),
+ NullS, NullS, name);
+}
+
+
+Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
+ uint start_in_q,
+ uint length_in_q)
+{
+ sp_variable *spv;
+ DBUG_ASSERT(spcont);
+ if ((spv= spcont->find_variable(name, false)))
+ {
+ /* We're compiling a stored procedure and found a variable */
+ if (!parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ return NULL;
+ }
+
+ Item_splocal *splocal= spv->field_def.is_column_type_ref() ?
+ new (thd->mem_root) Item_splocal_with_delayed_data_type(thd, name,
+ spv->offset,
+ start_in_q,
+ length_in_q) :
+ spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() ?
+ new (thd->mem_root) Item_splocal_row(thd, name, spv->offset,
+ start_in_q, length_in_q) :
+ new (thd->mem_root) Item_splocal(thd, name,
+ spv->offset, spv->sql_type(),
+ start_in_q, length_in_q);
+ if (splocal == NULL)
+ return NULL;
+#ifndef DBUG_OFF
+ splocal->m_sp= sphead;
+#endif
+ safe_to_cache_query= 0;
+ return splocal;
+ }
+
+ if (thd->variables.sql_mode & MODE_ORACLE)
+ {
+ if (!my_strcasecmp(system_charset_info, name->str, "SQLCODE"))
+ return new (thd->mem_root) Item_func_sqlcode(thd);
+ if (!my_strcasecmp(system_charset_info, name->str, "SQLERRM"))
+ return new (thd->mem_root) Item_func_sqlerrm(thd);
+ }
+ return create_item_ident_nosp(thd, name);
+}
+
+
+Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
+ const char *start_in_q,
+ const char *end_in_q)
+{
+ DBUG_ASSERT(sphead);
+ return create_item_ident_sp(thd, name, start_in_q - sphead->m_tmp_query,
+ end_in_q - start_in_q);
+}
+
+
+/**
+ Generate instructions for:
+ SET x.y= expr;
+*/
+bool LEX::set_variable(const LEX_CSTRING *name1,
+ const LEX_CSTRING *name2,
+ Item *item)
+{
+ sp_variable *spv;
+ if (spcont && (spv= spcont->find_variable(name1, false)))
+ {
+ if (spv->field_def.is_table_rowtype_ref() ||
+ spv->field_def.is_cursor_rowtype_ref())
+ return sphead->set_local_variable_row_field_by_name(thd, spcont,
+ spv, name2,
+ item, this);
+ // A field of a ROW variable
+ uint row_field_offset;
+ return !spv->find_row_field(name1, name2, &row_field_offset) ||
+ sphead->set_local_variable_row_field(thd, spcont,
+ spv, row_field_offset,
+ item, this);
+ }
+
+ // A trigger field or a system variable
+ sys_var_with_base sysvar;
+ return init_internal_variable(&sysvar, name1, name2) ||
+ set_variable(&sysvar, item);
+}
+
+
#ifdef MYSQL_SERVER
uint binlog_unsafe_map[256];
@@ -5134,3 +7031,67 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
}
return 0;
}
+
+
+bool LEX::sp_add_cfetch(THD *thd, const LEX_CSTRING *name)
+{
+ uint offset;
+ sp_instr_cfetch *i;
+
+ if (!spcont->find_cursor(name, &offset, false))
+ {
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name->str);
+ return true;
+ }
+ i= new (thd->mem_root)
+ sp_instr_cfetch(sphead->instructions(), spcont, offset);
+ if (i == NULL || sphead->add_instr(i))
+ return true;
+ return false;
+}
+
+
+bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident)
+{
+ sql_command= SQLCOM_CREATE_VIEW;
+ /* first table in list is target VIEW name */
+ if (!select_lex.add_table_to_list(thd, table_ident, NULL,
+ TL_OPTION_UPDATING,
+ TL_IGNORE,
+ MDL_EXCLUSIVE))
+ return true;
+ query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
+ return false;
+}
+
+
+bool LEX::add_alter_view(THD *thd, uint16 algorithm,
+ enum_view_suid suid,
+ Table_ident *table_ident)
+{
+ if (sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
+ return true;
+ }
+ if (!(create_view= new (thd->mem_root)
+ Create_view_info(VIEW_ALTER, algorithm, suid)))
+ return true;
+ return create_or_alter_view_finalize(thd, table_ident);
+}
+
+
+bool LEX::add_create_view(THD *thd, DDL_options_st ddl,
+ uint16 algorithm, enum_view_suid suid,
+ Table_ident *table_ident)
+{
+ if (set_create_options_with_check(ddl))
+ return true;
+ if (!(create_view= new (thd->mem_root)
+ Create_view_info(ddl.or_replace() ?
+ VIEW_CREATE_OR_REPLACE :
+ VIEW_CREATE_NEW,
+ algorithm, suid)))
+ return true;
+ return create_or_alter_view_finalize(thd, table_ident);
+}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a1ef42861b4..3c7c99dff3d 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -30,9 +30,59 @@
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
#include "sql_trigger.h"
+#include "sp.h" // enum stored_procedure_type
+
/* YACC and LEX Definitions */
+
+/**
+ A string with metadata.
+ We'll add more flags here eventually, to know if the string has, e.g.:
+ - multi-byte characters
+ - bad byte sequences
+ - backslash escapes: 'a\nb'
+ - separator escapes: 'a''b'
+ and reuse the original query fragments instead of making the string
+ copy too early, in Lex_input_stream::get_text().
+ This will allow to avoid unnecessary copying, as well as
+ create more optimal Item types in sql_yacc.yy
+*/
+struct Lex_string_with_metadata_st: public LEX_CSTRING
+{
+ bool m_is_8bit; // True if the string has 8bit characters
+public:
+ void set_8bit(bool is_8bit) { m_is_8bit= is_8bit; }
+ // Get string repertoire by the 8-bit flag and the character set
+ uint repertoire(CHARSET_INFO *cs) const
+ {
+ return !m_is_8bit && my_charset_is_ascii_based(cs) ?
+ MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
+ }
+ // Get string repertoire by the 8-bit flag, for ASCII-based character sets
+ uint repertoire() const
+ {
+ return !m_is_8bit ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
+ }
+};
+
+
+enum sub_select_type
+{
+ UNSPECIFIED_TYPE,
+ /* following 3 enums should be as they are*/
+ UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE,
+ GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE
+};
+enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT};
+
+enum enum_view_suid
+{
+ VIEW_SUID_INVOKER= 0,
+ VIEW_SUID_DEFINER= 1,
+ VIEW_SUID_DEFAULT= 2
+};
+
/* These may not be declared yet */
class Table_ident;
class sql_exchange;
@@ -41,6 +91,8 @@ class sp_head;
class sp_name;
class sp_instr;
class sp_pcontext;
+class sp_variable;
+class sp_assignment_lex;
class st_alter_tablespace;
class partition_info;
class Event_parse_data;
@@ -52,7 +104,7 @@ class Key_part_spec;
class Item_window_func;
struct sql_digest_state;
class With_clause;
-
+class my_var;
#define ALLOC_ROOT_SET 1024
@@ -109,7 +161,7 @@ void binlog_unsafe_map_init();
struct sys_var_with_base
{
sys_var *var;
- LEX_STRING base_name;
+ LEX_CSTRING base_name;
};
struct LEX_TYPE
@@ -153,8 +205,10 @@ struct LEX_TYPE
#ifdef MYSQL_SERVER
-extern const LEX_STRING null_lex_str;
-extern const LEX_STRING empty_lex_str;
+extern const LEX_STRING empty_lex_str;
+extern const LEX_CSTRING empty_clex_str;
+extern const LEX_CSTRING star_clex_str;
+extern const LEX_CSTRING param_clex_str;
enum enum_sp_suid_behaviour
{
@@ -192,6 +246,27 @@ enum enum_view_create_mode
VIEW_CREATE_OR_REPLACE // check only that there are not such table
};
+
+class Create_view_info: public Sql_alloc
+{
+public:
+ LEX_CSTRING select; // The SELECT statement of CREATE VIEW
+ enum enum_view_create_mode mode;
+ uint16 algorithm;
+ uint8 check;
+ enum enum_view_suid suid;
+ Create_view_info(enum_view_create_mode mode_arg,
+ uint16 algorithm_arg,
+ enum_view_suid suid_arg)
+ :select(null_clex_str),
+ mode(mode_arg),
+ algorithm(algorithm_arg),
+ check(VIEW_CHECK_NONE),
+ suid(suid_arg)
+ { }
+};
+
+
enum enum_drop_mode
{
DROP_DEFAULT, // mode is not specified
@@ -204,6 +279,7 @@ enum enum_drop_mode
#define TL_OPTION_FORCE_INDEX 2
#define TL_OPTION_IGNORE_LEAVES 4
#define TL_OPTION_ALIAS 8
+#define TL_OPTION_SEQUENCE 16
typedef List<Item> List_item;
typedef Mem_root_array<ORDER*, true> Group_list_ptrs;
@@ -212,11 +288,11 @@ typedef Mem_root_array<ORDER*, true> Group_list_ptrs;
typedef struct st_lex_server_options
{
long port;
- LEX_STRING server_name, host, db, username, password, scheme, socket, owner;
- void reset(LEX_STRING name)
+ LEX_CSTRING server_name, host, db, username, password, scheme, socket, owner;
+ void reset(LEX_CSTRING name)
{
server_name= name;
- host= db= username= password= scheme= socket= owner= null_lex_str;
+ host= db= username= password= scheme= socket= owner= null_clex_str;
port= -1;
}
} LEX_SERVER_OPTIONS;
@@ -234,13 +310,13 @@ struct LEX_MASTER_INFO
DYNAMIC_ARRAY repl_ignore_server_ids;
DYNAMIC_ARRAY repl_do_domain_ids;
DYNAMIC_ARRAY repl_ignore_domain_ids;
- char *host, *user, *password, *log_file_name;
- char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
- char *ssl_crl, *ssl_crlpath;
- char *relay_log_name;
- LEX_STRING connection_name;
+ const char *host, *user, *password, *log_file_name;
+ const char *ssl_key, *ssl_cert, *ssl_ca, *ssl_capath, *ssl_cipher;
+ const char *ssl_crl, *ssl_crlpath;
+ const char *relay_log_name;
+ LEX_CSTRING connection_name;
/* Value in START SLAVE UNTIL master_gtid_pos=xxx */
- LEX_STRING gtid_pos_str;
+ LEX_CSTRING gtid_pos_str;
ulonglong pos;
ulong relay_log_pos;
ulong server_id;
@@ -286,7 +362,7 @@ struct LEX_MASTER_INFO
ssl= ssl_verify_server_cert= heartbeat_opt=
repl_ignore_server_ids_opt= repl_do_domain_ids_opt=
repl_ignore_domain_ids_opt= LEX_MI_UNCHANGED;
- gtid_pos_str= null_lex_str;
+ gtid_pos_str= null_clex_str;
use_gtid_opt= LEX_GTID_UNCHANGED;
sql_delay= -1;
}
@@ -297,12 +373,6 @@ typedef struct st_lex_reset_slave
bool all;
} LEX_RESET_SLAVE;
-enum sub_select_type
-{
- UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,
- EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE
-};
-
enum olap_type
{
UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE
@@ -340,10 +410,10 @@ public:
The index name. Empty (str=NULL) name represents an empty list
USE INDEX () clause
*/
- LEX_STRING key_name;
+ LEX_CSTRING key_name;
Index_hint (enum index_hint_type type_arg, index_clause_map clause_arg,
- char *str, uint length) :
+ const char *str, uint length) :
type(type_arg), clause(clause_arg)
{
key_name.str= str;
@@ -540,7 +610,7 @@ public:
virtual List<Item>* get_item_list();
virtual ulong get_table_join_options();
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
- LEX_STRING *alias,
+ LEX_CSTRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
enum_mdl_type mdl_type= MDL_SHARED_READ,
@@ -562,7 +632,7 @@ public:
st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert,
st_select_lex_node *end_chain_node);
friend class st_select_lex_unit;
- friend bool mysql_new_select(LEX *lex, bool move_down);
+ friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
bool open_view_no_parse);
friend bool mysql_derived_prepare(THD *thd, LEX *lex,
@@ -582,7 +652,7 @@ typedef class st_select_lex_node SELECT_LEX_NODE;
class THD;
class select_result;
class JOIN;
-class select_union;
+class select_unit;
class Procedure;
class Explain_query;
@@ -594,10 +664,18 @@ bool print_explain_for_slow_log(LEX *lex, THD *thd, String *str);
class st_select_lex_unit: public st_select_lex_node {
protected:
TABLE_LIST result_table_list;
- select_union *union_result;
+ select_unit *union_result;
ulonglong found_rows_for_union;
bool saved_error;
+ bool prepare_join(THD *thd, SELECT_LEX *sl, select_result *result,
+ ulong additional_options,
+ bool is_union_select);
+ bool join_union_item_types(THD *thd, List<Item> &types, uint count);
+ bool join_union_type_handlers(THD *thd,
+ class Type_holder *holders, uint count);
+ bool join_union_type_attributes(THD *thd,
+ class Type_holder *holders, uint count);
public:
// Ensures that at least all members used during cleanup() are initialized.
st_select_lex_unit()
@@ -628,6 +706,11 @@ public:
*/
List<Item> types;
/**
+ There is INTERSECT and it is item used in creating temporary
+ table for it
+ */
+ Item_int *intersect_mark;
+ /**
Pointer to 'last' select, or pointer to select where we stored
global parameters for union.
@@ -718,19 +801,20 @@ public:
select_result_interceptor *old_result);
void set_limit(st_select_lex *values);
void set_thd(THD *thd_arg) { thd= thd_arg; }
- inline bool is_union ();
+ inline bool is_unit_op ();
bool union_needs_tmp_table();
void set_unique_exclude();
- friend void lex_start(THD *thd);
+ friend struct LEX;
friend int subselect_union_engine::exec();
List<Item> *get_column_types(bool for_cursor);
- select_union *get_union_result() { return union_result; }
+ select_unit *get_union_result() { return union_result; }
int save_union_explain(Explain_query *output);
int save_union_explain_part2(Explain_query *output);
+ unit_common_op common_op();
};
typedef class st_select_lex_unit SELECT_LEX_UNIT;
@@ -758,7 +842,7 @@ class st_select_lex: public st_select_lex_node
{
public:
Name_resolution_context context;
- char *db;
+ const char *db;
Item *where, *having; /* WHERE & HAVING clauses */
Item *prep_where; /* saved WHERE clause for prepared statement processing */
Item *prep_having;/* saved HAVING clause for prepared statement processing */
@@ -871,7 +955,8 @@ public:
int nest_level; /* nesting level of select */
Item_sum *inner_sum_func_list; /* list of sum func in nested selects */
uint with_wild; /* item list contain '*' */
- bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
+ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
+ bool automatic_brackets; /* dummy select for INTERSECT precedence */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
/* List of references to fields referenced from inner selects */
@@ -987,7 +1072,7 @@ public:
bool add_order_to_list(THD *thd, Item *item, bool asc);
bool add_gorder_to_list(THD *thd, Item *item, bool asc);
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
- LEX_STRING *alias,
+ LEX_CSTRING *alias,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
enum_mdl_type mdl_type= MDL_SHARED_READ,
@@ -1034,8 +1119,8 @@ public:
*/
ha_rows get_limit();
- friend void lex_start(THD *thd);
- st_select_lex() : group_list_ptrs(NULL), braces(0),
+ friend struct LEX;
+ st_select_lex() : group_list_ptrs(NULL), braces(0), automatic_brackets(0),
n_sum_items(0), n_child_sum_items(0)
{}
void make_empty_select()
@@ -1067,7 +1152,7 @@ public:
Add a index hint to the tagged list of hints. The type and clause of the
hint will be the current ones (set by set_index_hint())
*/
- bool add_index_hint (THD *thd, char *str, uint length);
+ bool add_index_hint (THD *thd, const char *str, uint length);
/* make a list to hold index hints */
void alloc_index_hints (THD *thd);
@@ -1080,7 +1165,7 @@ public:
}
void clear_index_hints(void) { index_hints= NULL; }
- bool is_part_of_union() { return master_unit()->is_union(); }
+ bool is_part_of_union() { return master_unit()->is_unit_op(); }
bool is_top_level_node()
{
return (select_number == 1) && !is_part_of_union();
@@ -1145,11 +1230,11 @@ public:
List<Window_spec> window_specs;
void prepare_add_window_spec(THD *thd);
- bool add_window_def(THD *thd, LEX_STRING *win_name, LEX_STRING *win_ref,
+ bool add_window_def(THD *thd, LEX_CSTRING *win_name, LEX_CSTRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame);
- bool add_window_spec(THD *thd, LEX_STRING *win_ref,
+ bool add_window_spec(THD *thd, LEX_CSTRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame);
@@ -1183,22 +1268,34 @@ public:
};
typedef class st_select_lex SELECT_LEX;
-inline bool st_select_lex_unit::is_union ()
-{
- return first_select()->next_select() &&
- first_select()->next_select()->linkage == UNION_TYPE;
+inline bool st_select_lex_unit::is_unit_op ()
+{
+ if (!first_select()->next_select())
+ return 0;
+
+ enum sub_select_type linkage= first_select()->next_select()->linkage;
+ return linkage == UNION_TYPE || linkage == INTERSECT_TYPE ||
+ linkage == EXCEPT_TYPE;
}
struct st_sp_chistics
{
- LEX_STRING comment;
+ LEX_CSTRING comment;
enum enum_sp_suid_behaviour suid;
bool detistic;
enum enum_sp_data_access daccess;
+ void init() { bzero(this, sizeof(*this)); }
+ void set(const st_sp_chistics &other) { *this= other; }
};
+class Sp_chistics: public st_sp_chistics
+{
+public:
+ Sp_chistics() { init(); }
+};
+
struct st_trg_chistics: public st_trg_execution_order
{
@@ -2183,6 +2280,20 @@ public:
return m_cpp_tok_end;
}
+ /**
+ Get the token end position in the pre-processed buffer,
+ with trailing spaces removed.
+ */
+ const char *get_cpp_tok_end_rtrim()
+ {
+ const char *p;
+ for (p= m_cpp_tok_end;
+ p > m_cpp_buf && my_isspace(system_charset_info, p[-1]);
+ p--)
+ { }
+ return p;
+ }
+
/** Get the current stream pointer, in the pre-processed buffer. */
const char *get_cpp_ptr()
{
@@ -2211,10 +2322,10 @@ public:
void body_utf8_append(const char *ptr);
void body_utf8_append(const char *ptr, const char *end_ptr);
void body_utf8_append_ident(THD *thd,
- const LEX_STRING *txt,
+ const LEX_CSTRING *txt,
const char *end_ptr);
void body_utf8_append_escape(THD *thd,
- const LEX_STRING *txt,
+ const LEX_CSTRING *txt,
CHARSET_INFO *txt_cs,
const char *end_ptr,
my_wc_t sep);
@@ -2238,7 +2349,8 @@ public:
/** LALR(2) resolution, value of the look ahead token.*/
LEX_YYSTYPE lookahead_yylval;
- bool get_text(LEX_STRING *to, uint sep, int pre_skip, int post_skip);
+ bool get_text(Lex_string_with_metadata_st *to,
+ uint sep, int pre_skip, int post_skip);
void add_digest_token(uint token, LEX_YYSTYPE yylval);
@@ -2317,9 +2429,6 @@ public:
*/
const char *found_semicolon;
- /** Token character bitmaps, to detect 7bit strings. */
- uchar tok_bitmap;
-
/** SQL_MODE = IGNORE_SPACE. */
bool ignore_space;
@@ -2534,21 +2643,23 @@ struct LEX: public Query_tables_list
*/
With_clause **with_clauses_list_last_next;
+ Create_view_info *create_view;
+
/* Query Plan Footprint of a currently running select */
Explain_query *explain;
// type information
CHARSET_INFO *charset;
- LEX_STRING name;
- char *help_arg;
- char *backup_dir; /* For RESTORE/BACKUP */
- char* to_log; /* For PURGE MASTER LOGS TO */
- char* x509_subject,*x509_issuer,*ssl_cipher;
+ LEX_CSTRING name;
+ const char *help_arg;
+ const char *backup_dir; /* For RESTORE/BACKUP */
+ const char* to_log; /* For PURGE MASTER LOGS TO */
+ const char* x509_subject,*x509_issuer,*ssl_cipher;
String *wild; /* Wildcard in SHOW {something} LIKE 'wild'*/
sql_exchange *exchange;
select_result *result;
- LEX_STRING comment, ident;
+ LEX_CSTRING comment, ident;
LEX_USER *grant_user;
XID *xid;
THD *thd;
@@ -2557,11 +2668,6 @@ struct LEX: public Query_tables_list
DYNAMIC_ARRAY plugins;
plugin_ref plugins_static_buffer[INITIAL_LEX_PLUGIN_LIST_SIZE];
- bool text_string_is_7bit;
-
- /** SELECT of CREATE VIEW statement */
- LEX_STRING create_view_select;
-
uint number_of_selects; // valid only for view
/** Start of 'ON table', in trigger statements. */
@@ -2578,6 +2684,7 @@ struct LEX: public Query_tables_list
*/
LEX_USER *definer;
+ Table_type table_type; /* Used for SHOW CREATE */
List<Key_part_spec> ref_list;
List<LEX_USER> users_list;
List<LEX_COLUMN> columns;
@@ -2590,6 +2697,18 @@ private:
Query_arena_memroot *arena_for_set_stmt;
MEM_ROOT *mem_root_for_set_stmt;
void parse_error();
+ bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
+ class sp_label **splabel);
+ bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive);
+ bool sp_exit_block(THD *thd, sp_label *lab);
+ bool sp_exit_block(THD *thd, sp_label *lab, Item *when);
+
+ bool sp_continue_loop(THD *thd, sp_label *lab);
+ bool sp_continue_loop(THD *thd, sp_label *lab, Item *when);
+
+ bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop);
+ bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop);
+
public:
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
bool set_arena_for_set_stmt(Query_arena *backup);
@@ -2599,7 +2718,7 @@ public:
List<Item_func_set_user_var> set_var_list; // in-query assignment list
List<Item_param> param_list;
List<LEX_STRING> view_list; // view list (list of field names in view)
- List<LEX_STRING> with_column_list; // list of column names in with_list_element
+ List<LEX_CSTRING> with_column_list; // list of column names in with_list_element
List<LEX_STRING> *column_list; // list of column names (in ANALYZE)
List<LEX_STRING> *index_list; // list of index names (in ANALYZE)
/*
@@ -2627,7 +2746,7 @@ public:
Key *last_key;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
LEX_SERVER_OPTIONS server_options;
- LEX_STRING relay_log_connection_name;
+ LEX_CSTRING relay_log_connection_name;
USER_RESOURCES mqh;
LEX_RESET_SLAVE reset_slave_info;
ulonglong type;
@@ -2675,7 +2794,6 @@ public:
bool with_persistent_for_clause; // uses PERSISTENT FOR clause (in ANALYZE)
};
enum enum_var_type option_type;
- enum enum_view_create_mode create_view_mode;
enum enum_drop_mode drop_mode;
uint profile_query_id;
@@ -2701,8 +2819,6 @@ public:
DERIVED_SUBQUERY and DERIVED_VIEW).
*/
uint8 derived_tables;
- uint16 create_view_algorithm;
- uint8 create_view_check;
uint8 context_analysis_only;
bool local_file;
bool check_exists;
@@ -2721,7 +2837,7 @@ public:
*/
TABLE_LIST *create_last_non_select_table;
/* Prepared statements SQL syntax:*/
- LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
+ LEX_CSTRING prepared_stmt_name; /* Statement name (in all queries) */
/* PREPARE or EXECUTE IMMEDIATE source expression */
Item *prepared_stmt_code;
/* Names of user variables holding parameters (in EXECUTE) */
@@ -2738,16 +2854,11 @@ public:
Event_parse_data *event_parse_data;
- bool only_view; /* used for SHOW CREATE TABLE/VIEW */
/*
field_list was created for view and should be removed before PS/SP
rexecuton
*/
bool empty_field_list_on_rset;
- /*
- view created to be run from definer (standard behaviour)
- */
- uint8 create_view_suid;
/* Characterstics of trigger being created */
st_trg_chistics trg_chistics;
/*
@@ -2843,7 +2954,7 @@ public:
SQL_I_List<ORDER> save_group_list;
SQL_I_List<ORDER> save_order_list;
- LEX_STRING *win_ref;
+ LEX_CSTRING *win_ref;
Window_frame *win_frame;
Window_frame_bound *frame_top_bound;
Window_frame_bound *frame_bottom_bound;
@@ -2870,6 +2981,18 @@ public:
delete_dynamic(&plugins);
}
+ virtual class Query_arena *query_arena()
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+
+ virtual const LEX_CSTRING *cursor_name() const { return &null_clex_str; }
+
+ void start(THD *thd);
+
+ const char *substatement_query(THD *thd) const;
+
inline bool is_ps_or_view_context_analysis()
{
return (context_analysis_only &
@@ -2955,7 +3078,7 @@ public:
context_stack.pop();
}
- bool copy_db_to(char **p_db, size_t *p_db_length) const;
+ bool copy_db_to(const char **p_db, size_t *p_db_length) const;
Name_resolution_context *current_context()
{
@@ -3000,8 +3123,8 @@ public:
bool is_analyze, bool *printed_anything);
void restore_set_statement_var();
- void init_last_field(Column_definition *field, const char *name, CHARSET_INFO *cs);
- void set_last_field_type(const Lex_field_type_st &type);
+ void init_last_field(Column_definition *field, const LEX_CSTRING *name,
+ const CHARSET_INFO *cs);
bool set_bincmp(CHARSET_INFO *cs, bool bin);
bool get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer);
@@ -3016,6 +3139,395 @@ public:
}
return false;
}
+ sp_variable *sp_param_init(LEX_CSTRING *name);
+ bool sp_param_fill_definition(sp_variable *spvar);
+
+ int case_stmt_action_expr(Item* expr);
+ int case_stmt_action_when(Item *when, bool simple);
+ int case_stmt_action_then();
+ bool add_select_to_union_list(bool is_union_distinct,
+ enum sub_select_type type,
+ bool is_top_level);
+ bool setup_select_in_parentheses();
+ bool set_trigger_new_row(LEX_CSTRING *name, Item *val);
+ bool set_system_variable(struct sys_var_with_base *tmp,
+ enum enum_var_type var_type, Item *val);
+ void set_stmt_init();
+ sp_name *make_sp_name(THD *thd, LEX_CSTRING *name);
+ sp_name *make_sp_name(THD *thd, LEX_CSTRING *name1, LEX_CSTRING *name2);
+ sp_head *make_sp_head(THD *thd, sp_name *name,
+ enum stored_procedure_type type);
+ sp_head *make_sp_head_no_recursive(THD *thd, sp_name *name,
+ enum stored_procedure_type type)
+ {
+ if (!sphead)
+ return make_sp_head(thd, name, type);
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0),
+ stored_procedure_type_to_str(type));
+ return NULL;
+ }
+ sp_head *make_sp_head_no_recursive(THD *thd,
+ DDL_options_st options, sp_name *name,
+ enum stored_procedure_type type)
+ {
+ if (add_create_options_with_check(options))
+ return NULL;
+ return make_sp_head_no_recursive(thd, name, type);
+ }
+ bool init_internal_variable(struct sys_var_with_base *variable,
+ const LEX_CSTRING *name);
+ bool init_internal_variable(struct sys_var_with_base *variable,
+ const LEX_CSTRING *dbname,
+ const LEX_CSTRING *name);
+ bool init_default_internal_variable(struct sys_var_with_base *variable,
+ LEX_CSTRING name);
+ bool set_variable(struct sys_var_with_base *variable, Item *item);
+ bool set_variable(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
+ Item *item);
+ void sp_variable_declarations_init(THD *thd, int nvars);
+ bool sp_variable_declarations_finalize(THD *thd, int nvars,
+ const Column_definition *cdef,
+ Row_definition_list *row,
+ Item *def);
+ bool sp_variable_declarations_finalize(THD *thd, int nvars,
+ const Column_definition *cdef,
+ Item *def)
+ {
+ return sp_variable_declarations_finalize(thd, nvars, cdef, NULL, def);
+ }
+ bool sp_variable_declarations_row_finalize(THD *thd, int nvars,
+ Row_definition_list *row,
+ Item *def)
+ {
+ return sp_variable_declarations_finalize(thd, nvars, NULL, row, def);
+ }
+ bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
+ Qualified_column_ident *col,
+ Item *def);
+ bool sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
+ Qualified_column_ident *,
+ Item *def);
+ bool sp_handler_declaration_init(THD *thd, int type);
+ bool sp_handler_declaration_finalize(THD *thd, int type);
+
+ bool sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
+ class sp_lex_cursor *cursor_stmt,
+ sp_pcontext *param_ctx, bool add_cpush_instr);
+
+ bool sp_open_cursor(THD *thd, const LEX_CSTRING *name,
+ List<sp_assignment_lex> *parameters);
+ Item_splocal *create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar,
+ const char *start_in_q,
+ const char *end_in_q);
+
+ Item *create_item_ident_nosp(THD *thd, LEX_CSTRING *name);
+ Item *create_item_ident_sp(THD *thd, LEX_CSTRING *name,
+ uint start_in_q,
+ uint length_in_q);
+ Item *create_item_ident_sp(THD *thd, LEX_CSTRING *name,
+ const char *start_in_q,
+ const char *end_in_q);
+ Item *create_item_ident(THD *thd, LEX_CSTRING *name,
+ const char *start_in_q,
+ const char *end_in_q)
+ {
+ return sphead ?
+ create_item_ident_sp(thd, name, start_in_q, end_in_q) :
+ create_item_ident_nosp(thd, name);
+ }
+
+ /*
+ Create an Item corresponding to a qualified name: a.b
+ when the parser is out of an SP context.
+ @param THD - THD, for mem_root
+ @param a - the first name
+ @param b - the second name
+ @retval - a pointer to a created item, or NULL on error.
+
+ Possible Item types that can be created:
+ - Item_trigger_field
+ - Item_field
+ - Item_ref
+ */
+ Item *create_item_ident_nospvar(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b);
+ /*
+ Create an Item corresponding to a ROW field valiable: var.field
+ @param THD - THD, for mem_root
+ @param var - the ROW variable name
+ @param field - the ROW variable field name
+ @param spvar - the variable that was previously found by name
+ using "var_name".
+ @pos_in_q - position in the query (for binary log)
+ @length_in_q - length in the query (for binary log)
+ */
+ Item_splocal *create_item_spvar_row_field(THD *thd,
+ const LEX_CSTRING *var,
+ const LEX_CSTRING *field,
+ sp_variable *spvar,
+ uint pos_in_q,
+ uint length_in_q);
+ /*
+ Create an item from its qualified name.
+ Depending on context, it can be either a ROW variable field,
+ or trigger, table field, table field reference.
+ See comments to create_item_spvar_row_field() and
+ create_item_ident_nospvar().
+ @param thd - THD, for mem_root
+ @param a - the first name
+ @param b - the second name
+ @param pos_in_q - position in the query (for binary log)
+ @param length_in_q - length in the query (for binary log)
+ @retval - NULL on error, or a pointer to a new Item.
+ */
+ Item *create_item_ident(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ uint pos_in_q, uint length_in_q);
+
+ /*
+ Create an item from its qualified name.
+ Depending on context, it can be a table field, a table field reference,
+ or a sequence NEXTVAL and CURRVAL.
+ @param thd - THD, for mem_root
+ @param a - the first name
+ @param b - the second name
+ @param c - the third name
+ @retval - NULL on error, or a pointer to a new Item.
+ */
+ Item *create_item_ident(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ const LEX_CSTRING *c);
+
+ /*
+ Create an item for "NEXT VALUE FOR sequence_name"
+ */
+ Item *create_item_func_nextval(THD *thd, Table_ident *ident);
+ Item *create_item_func_nextval(THD *thd, const LEX_CSTRING *db,
+ const LEX_CSTRING *name);
+ /*
+ Create an item for "PREVIOUS VALUE FOR sequence_name"
+ */
+ Item *create_item_func_lastval(THD *thd, Table_ident *ident);
+ Item *create_item_func_lastval(THD *thd, const LEX_CSTRING *db,
+ const LEX_CSTRING *name);
+
+ /*
+ Create an item for "SETVAL(sequence_name, value [, is_used [, round]])
+ */
+ Item *create_item_func_setval(THD *thd, Table_ident *ident, longlong value,
+ ulonglong round, bool is_used);
+
+ /*
+ Create an item for a name in LIMIT clause: LIMIT var
+ @param THD - THD, for mem_root
+ @param var_name - the variable name
+ @param pos_in_q - position in the query (for binary log)
+ @param length_in_q - length in the query (for binary log)
+ @retval - a new Item corresponding to the SP variable,
+ or NULL on error
+ (non in SP, unknown variable, wrong data type).
+ */
+ Item *create_item_limit(THD *thd,
+ const LEX_CSTRING *var_name,
+ uint pos_in_q, uint length_in_q);
+
+ /*
+ Create an item for a qualified name in LIMIT clause: LIMIT var.field
+ @param THD - THD, for mem_root
+ @param var_name - the variable name
+ @param field_name - the variable field name
+ @param pos_in_q - position in the query (for binary log)
+ @param length_in_q - length in the query (for binary log)
+ @retval - a new Item corresponding to the SP variable,
+ or NULL on error
+ (non in SP, unknown variable, unknown ROW field,
+ wrong data type).
+ */
+ Item *create_item_limit(THD *thd,
+ const LEX_CSTRING *var_name,
+ const LEX_CSTRING *field_name,
+ uint pos_in_q, uint length_in_q);
+
+ /*
+ Create a my_var instance for a ROW field variable that was used
+ as an OUT SP parameter: CALL p1(var.field);
+ @param THD - THD, for mem_root
+ @param var_name - the variable name
+ @param field_name - the variable field name
+ */
+ my_var *create_outvar(THD *thd,
+ const LEX_CSTRING *var_name,
+ const LEX_CSTRING *field_name);
+
+ bool is_trigger_new_or_old_reference(const LEX_CSTRING *name);
+
+ Item *create_and_link_Item_trigger_field(THD *thd, const LEX_CSTRING *name,
+ bool new_row);
+
+ void sp_block_init(THD *thd, const LEX_CSTRING *label);
+ void sp_block_init(THD *thd)
+ {
+ // Unlabeled blocks get an empty label
+ sp_block_init(thd, &empty_clex_str);
+ }
+ bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock)
+ {
+ class sp_label *tmp;
+ return sp_block_finalize(thd, spblock, &tmp);
+ }
+ bool sp_block_finalize(THD *thd)
+ {
+ return sp_block_finalize(thd, Lex_spblock());
+ }
+ bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
+ const LEX_CSTRING *end_label);
+ bool sp_block_finalize(THD *thd, const LEX_CSTRING *end_label)
+ {
+ return sp_block_finalize(thd, Lex_spblock(), end_label);
+ }
+ bool sp_declarations_join(Lex_spblock_st *res,
+ const Lex_spblock_st b1,
+ const Lex_spblock_st b2) const
+ {
+ if ((b2.vars || b2.conds) && (b1.curs || b1.hndlrs))
+ {
+ my_error(ER_SP_VARCOND_AFTER_CURSHNDLR, MYF(0));
+ return true;
+ }
+ if (b2.curs && b1.hndlrs)
+ {
+ my_error(ER_SP_CURSOR_AFTER_HANDLER, MYF(0));
+ return true;
+ }
+ res->join(b1, b2);
+ return false;
+ }
+ bool sp_block_with_exceptions_finalize_declarations(THD *thd);
+ bool sp_block_with_exceptions_finalize_executable_section(THD *thd,
+ uint executable_section_ip);
+ bool sp_block_with_exceptions_finalize_exceptions(THD *thd,
+ uint executable_section_ip,
+ uint exception_count);
+ bool sp_exit_statement(THD *thd, Item *when);
+ bool sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item);
+ bool sp_leave_statement(THD *thd, const LEX_CSTRING *label_name);
+ bool sp_goto_statement(THD *thd, const LEX_CSTRING *label_name);
+
+ bool sp_continue_statement(THD *thd, Item *when);
+ bool sp_continue_statement(THD *thd, const LEX_CSTRING *label_name, Item *when);
+ bool sp_iterate_statement(THD *thd, const LEX_CSTRING *label_name);
+
+ bool maybe_start_compound_statement(THD *thd);
+ bool sp_push_loop_label(THD *thd, const LEX_CSTRING *label_name);
+ bool sp_push_loop_empty_label(THD *thd);
+ bool sp_pop_loop_label(THD *thd, const LEX_CSTRING *label_name);
+ void sp_pop_loop_empty_label(THD *thd);
+ bool sp_while_loop_expression(THD *thd, Item *expr);
+ bool sp_while_loop_finalize(THD *thd);
+ bool sp_push_goto_label(THD *thd, const LEX_CSTRING *label_name);
+
+ Item_param *add_placeholder(THD *thd, const LEX_CSTRING *name,
+ uint pos_in_query, uint len_in_query);
+ Item_param *add_placeholder(THD *thd, const LEX_CSTRING *name,
+ const char *pos, const char *end)
+ {
+ return add_placeholder(thd, name, pos - substatement_query(thd), end - pos);
+ }
+
+ /* Integer range FOR LOOP methods */
+ sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
+ Item *value);
+ sp_variable *sp_add_for_loop_upper_bound(THD *thd, Item *value)
+ {
+ LEX_CSTRING name= { C_STRING_WITH_LEN("[upper_bound]") };
+ return sp_add_for_loop_variable(thd, &name, value);
+ }
+ bool sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
+ const LEX_CSTRING *index,
+ const Lex_for_loop_bounds_st &bounds);
+ bool sp_for_loop_intrange_condition_test(THD *thd, const Lex_for_loop_st &loop);
+ bool sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop);
+
+ /* Cursor FOR LOOP methods */
+ bool sp_for_loop_cursor_declarations(THD *thd, Lex_for_loop_st *loop,
+ const LEX_CSTRING *index,
+ const Lex_for_loop_bounds_st &bounds);
+ sp_variable *sp_add_for_loop_cursor_variable(THD *thd,
+ const LEX_CSTRING *name,
+ const class sp_pcursor *cur,
+ uint coffset,
+ sp_assignment_lex *param_lex,
+ Item_args *parameters);
+ bool sp_for_loop_cursor_condition_test(THD *thd, const Lex_for_loop_st &loop);
+ bool sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &);
+
+ /* Generic FOR LOOP methods*/
+
+ /*
+ Generate FOR loop declarations and
+ initialize "loop" from "index" and "bounds".
+
+ @param [IN] thd - current THD, for mem_root and error reporting
+ @param [OUT] loop - the loop generated SP variables are stored here,
+ together with additional loop characteristics.
+ @param [IN] index - the loop index variable name
+ @param [IN] bounds - the loop bounds (in sp_assignment_lex format)
+ and additional loop characteristics,
+ as created by the sp_for_loop_bounds rule.
+ @retval true - on error
+ @retval false - on success
+
+ This methods adds declarations:
+ - An explicit integer or cursor%ROWTYPE "index" variable
+ - An implicit integer upper bound variable, in case of integer range loops
+ - A CURSOR, in case of an implicit CURSOR loops
+ The generated variables are stored into "loop".
+ Additional loop characteristics are copied from "bounds" to "loop".
+ */
+ bool sp_for_loop_declarations(THD *thd, Lex_for_loop_st *loop,
+ const LEX_CSTRING *index,
+ const Lex_for_loop_bounds_st &bounds)
+ {
+ return bounds.is_for_loop_cursor() ?
+ sp_for_loop_cursor_declarations(thd, loop, index, bounds) :
+ sp_for_loop_intrange_declarations(thd, loop, index, bounds);
+ }
+
+ /*
+ Generate a conditional jump instruction to leave the loop,
+ using a proper condition depending on the loop type:
+ - Item_func_le -- integer range loops
+ - Item_func_ge -- integer range reverse loops
+ - Item_func_cursor_found -- cursor loops
+ */
+ bool sp_for_loop_condition_test(THD *thd, const Lex_for_loop_st &loop)
+ {
+ return loop.is_for_loop_cursor() ?
+ sp_for_loop_cursor_condition_test(thd, loop) :
+ sp_for_loop_intrange_condition_test(thd, loop);
+ }
+
+ /*
+ Generate "increment" instructions followed by a jump to the
+ condition test in the beginnig of the loop.
+ "Increment" depends on the loop type and can be:
+ - index:= index + 1; -- integer range loops
+ - index:= index - 1; -- integer range reverse loops
+ - FETCH cursor INTO index; -- cursor loops
+ */
+ bool sp_for_loop_finalize(THD *thd, const Lex_for_loop_st &loop)
+ {
+ return loop.is_for_loop_cursor() ?
+ sp_for_loop_cursor_finalize(thd, loop) :
+ sp_for_loop_intrange_finalize(thd, loop);
+ }
+ /* End of FOR LOOP methods */
+
+ bool add_signal_statement(THD *thd, const class sp_condition_value *value);
+ bool add_resignal_statement(THD *thd, const class sp_condition_value *value);
// Check if "KEY IF NOT EXISTS name" used outside of ALTER context
bool check_add_key(DDL_options_st ddl)
@@ -3028,7 +3540,7 @@ public:
return false;
}
// Add a key as a part of CREATE TABLE or ALTER TABLE
- bool add_key(Key::Keytype key_type, const LEX_STRING &key_name,
+ bool add_key(Key::Keytype key_type, const LEX_CSTRING *key_name,
ha_key_alg algorithm, DDL_options_st ddl)
{
if (check_add_key(ddl) ||
@@ -3038,7 +3550,7 @@ public:
return false;
}
// Add a key for a CREATE INDEX statement
- bool add_create_index(Key::Keytype key_type, const LEX_STRING &key_name,
+ bool add_create_index(Key::Keytype key_type, const LEX_CSTRING *key_name,
ha_key_alg algorithm, DDL_options_st ddl)
{
if (check_create_options(ddl) ||
@@ -3047,8 +3559,27 @@ public:
alter_info.key_list.push_back(last_key);
return false;
}
+ bool add_create_index_prepare(Table_ident *table)
+ {
+ sql_command= SQLCOM_CREATE_INDEX;
+ if (!current_select->add_table_to_list(thd, table, NULL,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_UPGRADABLE))
+ return true;
+ alter_info.reset();
+ alter_info.flags= Alter_info::ALTER_ADD_INDEX;
+ option_list= NULL;
+ return false;
+ }
+ /*
+ Add an UNIQUE or PRIMARY key which is a part of a column definition:
+ CREATE TABLE t1 (a INT PRIMARY KEY);
+ */
+ void add_key_to_list(LEX_CSTRING *field_name,
+ enum Key::Keytype type, bool check_exists);
// Add a constraint as a part of CREATE TABLE or ALTER TABLE
- bool add_constraint(LEX_STRING *name, Virtual_column_info *constr,
+ bool add_constraint(LEX_CSTRING *name, Virtual_column_info *constr,
bool if_not_exists)
{
constr->name= *name;
@@ -3079,11 +3610,18 @@ public:
}
return false;
}
+ bool set_create_options_with_check(DDL_options_st options)
+ {
+ create_info.set(options);
+ return check_create_options(create_info);
+ }
bool add_create_options_with_check(DDL_options_st options)
{
create_info.add(options);
return check_create_options(create_info);
}
+ bool sp_add_cfetch(THD *thd, const LEX_CSTRING *name);
+
bool set_command_with_check(enum_sql_command command,
uint scope,
DDL_options_st options)
@@ -3104,6 +3642,16 @@ public:
*/
bool tmp_table() const { return create_info.tmp_table(); }
bool if_exists() const { return create_info.if_exists(); }
+
+ SELECT_LEX *exclude_last_select();
+ bool add_unit_in_brackets(SELECT_LEX *nselect);
+ void check_automatic_up(enum sub_select_type type);
+ bool create_or_alter_view_finalize(THD *thd, Table_ident *table_ident);
+ bool add_alter_view(THD *thd, uint16 algorithm, enum_view_suid suid,
+ Table_ident *table_ident);
+ bool add_create_view(THD *thd, DDL_options_st ddl,
+ uint16 algorithm, enum_view_suid suid,
+ Table_ident *table_ident);
};
@@ -3285,6 +3833,92 @@ struct st_lex_local: public LEX, public Sql_alloc
{
};
+
+/**
+ An st_lex_local extension with automatic initialization for SP purposes.
+ Used to parse sub-expressions and SP sub-statements.
+
+ This class is reused for:
+ 1. sp_head::reset_lex() based constructs
+ - SP variable assignments (e.g. SET x=10;)
+ - FOR loop conditions and index variable increments
+ - Cursor statements
+ - SP statements
+ - SP function RETURN statements
+ - CASE statements
+ - REPEAT..UNTIL expressions
+ - WHILE expressions
+ - EXIT..WHEN and CONTINUE..WHEN statements
+ 2. sp_assignment_lex based constructs:
+ - CURSOR parameter assignments
+*/
+class sp_lex_local: public st_lex_local
+{
+public:
+ sp_lex_local(THD *thd, const LEX *oldlex)
+ {
+ /* Reset most stuff. */
+ start(thd);
+ /* Keep the parent SP stuff */
+ sphead= oldlex->sphead;
+ spcont= oldlex->spcont;
+ /* Keep the parent trigger stuff too */
+ trg_chistics= oldlex->trg_chistics;
+ trg_table_fields.empty();
+ sp_lex_in_use= false;
+ }
+};
+
+
+/**
+ An assignment specific LEX, which additionally has an Item (an expression)
+ and an associated with the Item free_list, which is usually freed
+ after the expression is calculated.
+
+ Note, consider changing some of sp_lex_local to sp_assignment_lex,
+ as the latter allows to use a simpler grammar in sql_yacc.yy (IMO).
+
+ If the expression is simple (e.g. does not have function calls),
+ then m_item and m_free_list point to the same Item.
+
+ If the expressions is complex (e.g. have function calls),
+ then m_item points to the leftmost Item, while m_free_list points
+ to the rightmost item.
+ For example:
+ f1(COALESCE(f2(10), f2(20)))
+ - m_item points to Item_func_sp for f1 (the leftmost Item)
+ - m_free_list points to Item_int for 20 (the rightmost Item)
+
+ Note, we could avoid storing m_item at all, as we can always reach
+ the leftmost item from the rightmost item by iterating through m_free_list.
+ But with a separate m_item the code should be faster.
+*/
+class sp_assignment_lex: public sp_lex_local
+{
+ Item *m_item; // The expression
+ Item *m_free_list; // The associated free_list (sub-expressions)
+public:
+ sp_assignment_lex(THD *thd, LEX *oldlex)
+ :sp_lex_local(thd, oldlex),
+ m_item(NULL),
+ m_free_list(NULL)
+ { }
+ void set_item_and_free_list(Item *item, Item *free_list)
+ {
+ m_item= item;
+ m_free_list= free_list;
+ }
+ Item *get_item() const
+ {
+ return m_item;
+ }
+ Item *get_free_list() const
+ {
+ return m_free_list;
+ }
+};
+
+
extern void lex_init(void);
extern void lex_free(void);
extern void lex_start(THD *thd);
@@ -3294,18 +3928,28 @@ extern void lex_end_stage2(LEX *lex);
void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex);
int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex);
extern int MYSQLlex(union YYSTYPE *yylval, THD *thd);
+extern int ORAlex(union YYSTYPE *yylval, THD *thd);
-extern void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str,
+extern void trim_whitespace(CHARSET_INFO *cs, LEX_CSTRING *str,
uint *prefix_removed);
-extern bool is_lex_native_function(const LEX_STRING *name);
+extern bool is_lex_native_function(const LEX_CSTRING *name);
+extern bool is_native_function(THD *thd, const LEX_CSTRING *name);
+extern bool is_native_function_with_warn(THD *thd, const LEX_CSTRING *name);
/**
@} (End of group Semantic_Analysis)
*/
-void my_missing_function_error(const LEX_STRING &token, const char *name);
+void my_missing_function_error(const LEX_CSTRING &token, const char *name);
bool is_keyword(const char *name, uint len);
+Virtual_column_info *add_virtual_expression(THD *thd, Item *expr);
+Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
+ Item *expr);
+
+void sp_create_assignment_lex(THD *thd, bool no_lookahead);
+bool sp_create_assignment_instr(THD *thd, bool no_lookahead);
+
#endif /* MYSQL_SERVER */
#endif /* SQL_LEX_INCLUDED */
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 8f6f7337f1c..e1307f1daa0 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -334,16 +334,15 @@ public:
friend class error_list;
friend class error_list_iterator;
-#ifndef DBUG_OFF
/*
- Debugging help: return N-th element in the list, or NULL if the list has
+ Return N-th element in the list, or NULL if the list has
less than N elements.
*/
- void *elem(int n)
+ void *elem(uint n)
{
list_node *node= first;
void *data= NULL;
- for (int i=0; i <= n; i++)
+ for (uint i= 0; i <= n; i++)
{
if (node == &end_of_list)
{
@@ -355,7 +354,6 @@ public:
}
return data;
}
-#endif
#ifdef LIST_EXTRA_DEBUG
/*
@@ -524,10 +522,10 @@ public:
base_list(tmp, mem_root) {}
inline bool push_back(T *a) { return base_list::push_back(a); }
inline bool push_back(T *a, MEM_ROOT *mem_root)
- { return base_list::push_back(a, mem_root); }
+ { return base_list::push_back((void*) a, mem_root); }
inline bool push_front(T *a) { return base_list::push_front(a); }
inline bool push_front(T *a, MEM_ROOT *mem_root)
- { return base_list::push_front(a, mem_root); }
+ { return base_list::push_front((void*) a, mem_root); }
inline T* head() {return (T*) base_list::head(); }
inline T** head_ref() {return (T**) base_list::head_ref(); }
inline T* pop() {return (T*) base_list::pop(); }
@@ -546,9 +544,7 @@ public:
}
empty();
}
-#ifndef DBUG_OFF
- T *elem(int n) { return (T*)base_list::elem(n); }
-#endif
+ T *elem(uint n) { return (T*) base_list::elem(n); }
};
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 06eb86dd694..132da4dff65 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -283,13 +283,13 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
killed_state killed_status;
bool is_concurrent;
#endif
- char *db = table_list->db; // This is never null
+ const char *db = table_list->db; // This is never null
/*
If path for file is not defined, we will use the current database.
If this is not set, we will use the directory where the table to be
loaded is located
*/
- char *tdb= thd->db ? thd->db : db; // Result is never null
+ const char *tdb= thd->db ? thd->db : db; // Result is never null
ulong skip_lines= ex->skip_lines;
bool transactional_table __attribute__((unused));
DBUG_ENTER("mysql_load");
@@ -812,7 +812,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
if (n++)
query_str.append(", ");
if (item->real_type() == Item::FIELD_ITEM)
- append_identifier(thd, &query_str, item->name, strlen(item->name));
+ append_identifier(thd, &query_str, item->name.str, item->name.length);
else
{
/* Actually Item_user_var_as_out_param despite claiming STRING_ITEM. */
@@ -836,8 +836,8 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
val= lv++;
if (n++)
query_str.append(STRING_WITH_LEN(", "));
- append_identifier(thd, &query_str, item->name, strlen(item->name));
- query_str.append(val->name);
+ append_identifier(thd, &query_str, item->name.str, item->name.length);
+ query_str.append(val->name.str, val->name.length);
}
}
@@ -1087,7 +1087,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
else if (!real_item)
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
DBUG_RETURN(1);
}
else
@@ -1095,7 +1095,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
Field *field= real_item->field;
if (field->reset())
{
- my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
+ my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name.str,
thd->get_stmt_da()->current_row_for_warning());
DBUG_RETURN(1);
}
@@ -1126,7 +1126,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
else if (!real_item)
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
DBUG_RETURN(1);
}
else
@@ -1166,7 +1166,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
}
else if (!real_item)
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
DBUG_RETURN(1);
}
else
@@ -1174,7 +1174,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
Field *field= real_item->field;
if (field->reset())
{
- my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
+ my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name.str,
thd->get_stmt_da()->current_row_for_warning());
DBUG_RETURN(1);
}
@@ -1296,7 +1296,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
xmlit.rewind();
tag= xmlit++;
- while(tag && strcmp(tag->field.c_ptr(), item->name) != 0)
+ while(tag && strcmp(tag->field.c_ptr(), item->name.str) != 0)
tag= xmlit++;
Item_field *real_item= item->field_for_view_update();
@@ -1306,7 +1306,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
((Item_user_var_as_out_param *) item)->set_null_value(cs);
else if (!real_item)
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
DBUG_RETURN(1);
}
else
@@ -1336,7 +1336,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
tag->value.length(), cs);
else if (!real_item)
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
DBUG_RETURN(1);
}
else
@@ -1373,7 +1373,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
((Item_user_var_as_out_param *)item)->set_null_value(cs);
else if (!real_item)
{
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
DBUG_RETURN(1);
}
else
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ac742d79681..f9be9019489 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -101,6 +101,7 @@
#include "set_var.h"
#include "log_slow.h"
#include "sql_bootstrap.h"
+#include "sql_sequence.h"
#include "my_json_writer.h"
@@ -448,14 +449,17 @@ static bool stmt_causes_implicit_commit(THD *thd, uint mask)
switch (lex->sql_command) {
case SQLCOM_DROP_TABLE:
+ case SQLCOM_DROP_SEQUENCE:
skip= (lex->tmp_table() ||
(thd->variables.option_bits & OPTION_GTID_BEGIN));
break;
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_ALTER_SEQUENCE:
/* If ALTER TABLE of non-temporary table, do implicit commit */
skip= (lex->tmp_table());
break;
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
/*
If CREATE TABLE of non-temporary table and the table is not part
if a BEGIN GTID ... COMMIT group, do a implicit commit.
@@ -542,19 +546,27 @@ void init_update_queries(void)
*/
sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
- CF_CAN_GENERATE_ROW_EVENTS;
+ CF_CAN_GENERATE_ROW_EVENTS |
+ CF_SCHEMA_CHANGE;
+ sql_command_flags[SQLCOM_CREATE_SEQUENCE]= (CF_CHANGES_DATA |
+ CF_REEXECUTION_FRAGILE |
+ CF_AUTO_COMMIT_TRANS |
+ CF_SCHEMA_CHANGE);
sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS;
sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
+ sql_command_flags[SQLCOM_ALTER_SEQUENCE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
+ CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_SCHEMA_CHANGE;
sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
CF_CAN_GENERATE_ROW_EVENTS | CF_REPORT_PROGRESS |
CF_INSERTS_DATA;
- sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
- sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
+ sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_DB_CHANGE;
+ sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS | CF_DB_CHANGE;
sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_ALTER_DB]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
@@ -721,6 +733,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_TRUNCATE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate DROP for temp tables in row format */
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* One can change replication mode with SET */
sql_command_flags[SQLCOM_SET_OPTION]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
@@ -763,6 +776,7 @@ void init_update_queries(void)
*/
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_PREOPEN_TMP_TABLES;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_TRUNCATE]|= CF_PREOPEN_TMP_TABLES;
@@ -795,7 +809,9 @@ void init_update_queries(void)
have to be closed before temporary tables are pre-opened.
*/
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE;
+ sql_command_flags[SQLCOM_CREATE_SEQUENCE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_HA_CLOSE;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_TRUNCATE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_REPAIR]|= CF_HA_CLOSE;
@@ -813,8 +829,10 @@ void init_update_queries(void)
even temporary table DDL should be disallowed.
*/
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_CREATE_SEQUENCE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
+ sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_RENAME_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_DISALLOW_IN_RO_TRANS;
sql_command_flags[SQLCOM_DROP_INDEX]|= CF_DISALLOW_IN_RO_TRANS;
@@ -1407,7 +1425,7 @@ out:
This is a helper function to mysql_execute_command.
- @note SQLCOM_MULTI_UPDATE is an exception and delt with elsewhere.
+ @note SQLCOM_MULTI_UPDATE is an exception and dealt with elsewhere.
@see mysql_execute_command
@returns Status code
@@ -1425,13 +1443,12 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
LEX *lex= thd->lex;
- const my_bool user_is_super=
- ((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
- (ulong)SUPER_ACL);
-
- if (user_is_super)
+ /* Super user is allowed to do changes */
+ if (((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
+ (ulong)SUPER_ACL))
DBUG_RETURN(FALSE);
+ /* Check if command doesn't update anything */
if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
DBUG_RETURN(FALSE);
@@ -1439,29 +1456,17 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
- const my_bool create_temp_tables=
- (lex->sql_command == SQLCOM_CREATE_TABLE) && lex->tmp_table();
-
- const my_bool drop_temp_tables=
- (lex->sql_command == SQLCOM_DROP_TABLE) && lex->tmp_table();
-
- const my_bool update_real_tables=
- some_non_temp_table_to_be_updated(thd, all_tables) &&
- !(create_temp_tables || drop_temp_tables);
-
-
- const my_bool create_or_drop_databases=
- (lex->sql_command == SQLCOM_CREATE_DB) ||
- (lex->sql_command == SQLCOM_DROP_DB);
+ /* Check if we created or dropped temporary tables */
+ if ((sql_command_flags[lex->sql_command] & CF_SCHEMA_CHANGE) &&
+ lex->tmp_table())
+ DBUG_RETURN(FALSE);
- if (update_real_tables || create_or_drop_databases)
- {
- /*
- An attempt was made to modify one or more non-temporary tables.
- */
- DBUG_RETURN(TRUE);
- }
+ /* Check if we created or dropped databases */
+ if ((sql_command_flags[lex->sql_command] & CF_DB_CHANGE))
+ DBUG_RETURN(TRUE);
+ if (some_non_temp_table_to_be_updated(thd, all_tables))
+ DBUG_RETURN(TRUE);
/* Assuming that only temporary tables are modified. */
DBUG_RETURN(FALSE);
@@ -1574,7 +1579,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (thd->wsrep_conflict_state == ABORTED &&
command != COM_STMT_CLOSE && command != COM_QUIT)
{
- my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction");
+ my_message(ER_LOCK_DEADLOCK, "wsrep aborted transaction", MYF(0));
WSREP_DEBUG("Deadlock error for: %s", thd->query());
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
thd->killed = NOT_KILLED;
@@ -1654,9 +1659,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
switch (command) {
case COM_INIT_DB:
{
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
status_var_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB]);
- if (thd->copy_with_error(system_charset_info, &tmp,
+ if (thd->copy_with_error(system_charset_info, (LEX_STRING*) &tmp,
thd->charset(), packet, packet_length))
break;
if (!mysql_change_db(thd, &tmp, FALSE))
@@ -1726,7 +1731,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (auth_rc)
{
/* Free user if allocated by acl_authenticate */
- my_free(thd->security_ctx->user);
+ my_free(const_cast<char*>(thd->security_ctx->user));
*thd->security_ctx= save_security_ctx;
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
@@ -1745,7 +1750,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
decrease_user_connections(save_user_connect);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
my_free(save_db);
- my_free(save_security_ctx.user);
+ my_free(const_cast<char*>(save_security_ctx.user));
}
break;
}
@@ -1922,7 +1927,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Locked closure of all tables */
TABLE_LIST table_list;
LEX_STRING table_name;
- LEX_STRING db;
+ LEX_CSTRING db;
/*
SHOW statements should not add the used tables to the list of tables
used in a transaction.
@@ -1969,7 +1974,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (lower_case_table_names)
{
table_name.length= my_casedn_str(files_charset_info, table_name.str);
- db.length= my_casedn_str(files_charset_info, db.str);
+ db.length= my_casedn_str(files_charset_info, (char*) db.str);
}
table_list.init_one_table(db.str, db.length, table_name.str,
table_name.length, table_name.str, TL_READ);
@@ -2110,7 +2115,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
else
#endif
{
- thd->lex->relay_log_connection_name= empty_lex_str;
+ thd->lex->relay_log_connection_name= empty_clex_str;
if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
break;
}
@@ -2291,7 +2296,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (server_command_flags[subcommand] & CF_NO_COM_MULTI)
{
- my_error(ER_BAD_COMMAND_IN_MULTI, MYF(0), command_name[subcommand]);
+ my_error(ER_BAD_COMMAND_IN_MULTI, MYF(0),
+ command_name[subcommand].str);
goto com_multi_end;
}
@@ -2533,10 +2539,16 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
DBUG_RETURN(1);
}
schema_select_lex= new (thd->mem_root) SELECT_LEX();
- db.str= schema_select_lex->db= lex->select_lex.db;
schema_select_lex->table_list.first= NULL;
+ if (lower_case_table_names == 1)
+ lex->select_lex.db= thd->strdup(lex->select_lex.db);
+ schema_select_lex->db= lex->select_lex.db;
+ /*
+ check_db_name() may change db.str if lower_case_table_names == 1,
+ but that's ok as the db is allocted above in this case.
+ */
+ db.str= (char*) lex->select_lex.db;
db.length= strlen(db.str);
-
if (check_db_name(&db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
@@ -2698,7 +2710,7 @@ bool sp_process_definer(THD *thd)
DBUG_RETURN(TRUE);
if (thd->slave_thread && lex->sphead)
- lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
+ lex->sphead->set_suid(SP_IS_NOT_SUID);
}
else
{
@@ -2863,7 +2875,7 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
if (!(thd->client_capabilities & CLIENT_MULTI_RESULTS))
{
/* The client does not support multiple result sets being sent back */
- my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
+ my_error(ER_SP_BADSELECT, MYF(0), ErrConvDQName(sp).ptr());
return 1;
}
/*
@@ -2902,6 +2914,174 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
}
+static int mysql_create_routine(THD *thd, LEX *lex)
+{
+ DBUG_ASSERT(lex->sphead != 0);
+ DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
+ /*
+ Verify that the database name is allowed, optionally
+ lowercase it.
+ */
+ if (check_db_name((LEX_STRING*) &lex->sphead->m_db))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
+ return true;
+ }
+
+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
+ NULL, NULL, 0, 0))
+ return true;
+
+ /* Checking the drop permissions if CREATE OR REPLACE is used */
+ if (lex->create_info.or_replace())
+ {
+ if (check_routine_access(thd, ALTER_PROC_ACL, lex->sphead->m_db.str,
+ lex->sphead->m_name.str,
+ lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
+ return true;
+ }
+
+ const LEX_CSTRING *name= lex->sphead->name();
+#ifdef HAVE_DLOPEN
+ if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
+ {
+ udf_func *udf = find_udf(name->str, name->length);
+
+ if (udf)
+ {
+ my_error(ER_UDF_EXISTS, MYF(0), name->str);
+ return true;
+ }
+ }
+#endif
+
+ if (sp_process_definer(thd))
+ return true;
+
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ if (!sp_create_routine(thd, lex->sphead->m_type, lex->sphead))
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* only add privileges if really neccessary */
+
+ Security_context security_context;
+ bool restore_backup_context= false;
+ Security_context *backup= NULL;
+ LEX_USER *definer= thd->lex->definer;
+ /*
+ We're going to issue an implicit GRANT statement so we close all
+ open tables. We have to keep metadata locks as this ensures that
+ this statement is atomic against concurent FLUSH TABLES WITH READ
+ LOCK. Deadlocks which can arise due to fact that this implicit
+ statement takes metadata locks should be detected by a deadlock
+ detector in MDL subsystem and reported as errors.
+
+ No need to commit/rollback statement transaction, it's not started.
+
+ TODO: Long-term we should either ensure that implicit GRANT statement
+ is written into binary log as a separate statement or make both
+ creation of routine and implicit GRANT parts of one fully atomic
+ statement.
+ */
+ DBUG_ASSERT(thd->transaction.stmt.is_empty());
+ close_thread_tables(thd);
+ /*
+ Check if the definer exists on slave,
+ then use definer privilege to insert routine privileges to mysql.procs_priv.
+
+ For current user of SQL thread has GLOBAL_ACL privilege,
+ which doesn't any check routine privileges,
+ so no routine privilege record will insert into mysql.procs_priv.
+ */
+ if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str))
+ {
+ security_context.change_security_context(thd,
+ &thd->lex->definer->user,
+ &thd->lex->definer->host,
+ &thd->lex->sphead->m_db,
+ &backup);
+ restore_backup_context= true;
+ }
+
+ if (sp_automatic_privileges && !opt_noacl &&
+ check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
+ lex->sphead->m_db.str, name->str,
+ lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
+ {
+ if (sp_grant_privileges(thd, lex->sphead->m_db.str, name->str,
+ lex->sql_command == SQLCOM_CREATE_PROCEDURE))
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_PROC_AUTO_GRANT_FAIL, ER_THD(thd, ER_PROC_AUTO_GRANT_FAIL));
+ thd->clear_error();
+ }
+
+ /*
+ Restore current user with GLOBAL_ACL privilege of SQL thread
+ */
+ if (restore_backup_context)
+ {
+ DBUG_ASSERT(thd->slave_thread == 1);
+ thd->security_ctx->restore_security_context(thd, backup);
+ }
+
+#endif
+ return false;
+ }
+#ifdef WITH_WSREP
+error: /* Used by WSREP_TO_ISOLATION_BEGIN */
+#endif
+ return true;
+}
+
+
+/**
+ Prepare for CREATE DATABASE, ALTER DATABASE, DROP DATABASE.
+
+ @param thd - current THD
+ @param want_access - access needed
+ @param dbname - the database name
+
+ @retval false - Ok to proceed with CREATE/ALTER/DROP
+ @retval true - not OK to proceed (error, or filtered)
+
+ Note, on slave this function returns true if the database
+ is in the ignore filter. The caller must distinguish this case
+ from other cases: bad database error, no access error.
+ This can be done by testing thd->is_error().
+*/
+static bool prepare_db_action(THD *thd, ulong want_access, LEX_CSTRING *dbname)
+{
+ if (check_db_name((LEX_STRING*)dbname))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname->str);
+ return true;
+ }
+ /*
+ If in a slave thread :
+ - CREATE DATABASE DB was certainly not preceded by USE DB.
+ - ALTER DATABASE DB may not be preceded by USE DB.
+ - DROP DATABASE DB may not be preceded by USE DB.
+ For that reason, db_ok() in sql/slave.cc did not check the
+ do_db/ignore_db. And as this query involves no tables, tables_ok()
+ was not called. So we have to check rules again here.
+ */
+#ifdef HAVE_REPLICATION
+ if (thd->slave_thread)
+ {
+ Rpl_filter *rpl_filter;
+ rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
+ if (!rpl_filter->db_ok(dbname->str) ||
+ !rpl_filter->db_ok_with_wild_table(dbname->str))
+ {
+ my_message(ER_SLAVE_IGNORED_TABLE,
+ ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
+ return true;
+ }
+ }
+#endif
+ return check_access(thd, want_access, dbname->str, NULL, NULL, 1, 0);
+}
+
/**
Execute command saved in thd and lex->sql_command.
@@ -3078,7 +3258,8 @@ mysql_execute_command(THD *thd)
*/
if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
!(lex->sql_command == SQLCOM_SET_OPTION) &&
- !(lex->sql_command == SQLCOM_DROP_TABLE &&
+ !((lex->sql_command == SQLCOM_DROP_TABLE ||
+ lex->sql_command == SQLCOM_DROP_SEQUENCE) &&
lex->tmp_table() && lex->if_exists()) &&
all_tables_not_ok(thd, all_tables))
{
@@ -3704,6 +3885,7 @@ mysql_execute_command(THD *thd)
res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX);
break;
}
+ case SQLCOM_CREATE_SEQUENCE:
case SQLCOM_CREATE_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -3961,6 +4143,7 @@ mysql_execute_command(THD *thd)
/* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table, &create_info, &alter_info);
}
+
if (!res)
{
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
@@ -4169,9 +4352,9 @@ end_with_restore_list:
*/
DBUG_PRINT("debug", ("lex->only_view: %d, table: %s.%s",
- lex->only_view,
+ lex->table_type == TABLE_TYPE_VIEW,
first_table->db, first_table->table_name));
- if (lex->only_view)
+ if (lex->table_type == TABLE_TYPE_VIEW)
{
if (check_table_access(thd, SELECT_ACL, first_table, FALSE, 1, FALSE))
{
@@ -4185,7 +4368,6 @@ end_with_restore_list:
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
first_table->open_type= OT_BASE_ONLY;
-
}
else
{
@@ -4694,6 +4876,7 @@ end_with_restore_list:
}
break;
}
+ case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -4704,7 +4887,7 @@ end_with_restore_list:
}
else
{
- status_var_decrement(thd->status_var.com_stat[SQLCOM_DROP_TABLE]);
+ status_var_decrement(thd->status_var.com_stat[lex->sql_command]);
status_var_increment(thd->status_var.com_drop_tmp_table);
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
@@ -4734,10 +4917,13 @@ end_with_restore_list:
lex->create_info.set(DDL_options_st::OPT_IF_EXISTS);
/* DDL and binlog write order are protected by metadata locks. */
- res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table());
+ res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table(),
+ lex->table_type == TABLE_TYPE_SEQUENCE);
- /* when dropping temporary tables if @@session_track_state_change is ON then
- send the boolean tracker in the OK packet */
+ /*
+ When dropping temporary tables if @@session_track_state_change is ON
+ then send the boolean tracker in the OK packet
+ */
if(!res && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
@@ -4778,7 +4964,7 @@ end_with_restore_list:
#endif
case SQLCOM_CHANGE_DB:
{
- LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
+ LEX_CSTRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
if (!mysql_change_db(thd, &db_str, FALSE))
my_ok(thd);
@@ -4901,33 +5087,9 @@ end_with_restore_list:
break;
case SQLCOM_CREATE_DB:
{
- if (check_db_name(&lex->name))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
- break;
- }
- /*
- If in a slave thread :
- CREATE DATABASE DB was certainly not preceded by USE DB.
- For that reason, db_ok() in sql/slave.cc did not check the
- do_db/ignore_db. And as this query involves no tables, tables_ok()
- above was not called. So we have to check rules again here.
- */
-#ifdef HAVE_REPLICATION
- if (thd->slave_thread)
- {
- rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
- if (!rpl_filter->db_ok(lex->name.str) ||
- !rpl_filter->db_ok_with_wild_table(lex->name.str))
- {
- my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
- break;
- }
- }
-#endif
- if (check_access(thd, lex->create_info.or_replace() ?
+ if (prepare_db_action(thd, lex->create_info.or_replace() ?
(CREATE_ACL | DROP_ACL) : CREATE_ACL,
- lex->name.str, NULL, NULL, 1, 0))
+ &lex->name))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
res= mysql_create_db(thd, lex->name.str,
@@ -4936,31 +5098,7 @@ end_with_restore_list:
}
case SQLCOM_DROP_DB:
{
- if (check_db_name(&lex->name))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str);
- break;
- }
- /*
- If in a slave thread :
- DROP DATABASE DB may not be preceded by USE DB.
- For that reason, maybe db_ok() in sql/slave.cc did not check the
- do_db/ignore_db. And as this query involves no tables, tables_ok()
- above was not called. So we have to check rules again here.
- */
-#ifdef HAVE_REPLICATION
- if (thd->slave_thread)
- {
- rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
- if (!rpl_filter->db_ok(lex->name.str) ||
- !rpl_filter->db_ok_with_wild_table(lex->name.str))
- {
- my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
- break;
- }
- }
-#endif
- if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
+ if (prepare_db_action(thd, DROP_ACL, &lex->name))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
res= mysql_rm_db(thd, lex->name.str, lex->if_exists());
@@ -4968,7 +5106,7 @@ end_with_restore_list:
}
case SQLCOM_ALTER_DB_UPGRADE:
{
- LEX_STRING *db= & lex->name;
+ LEX_CSTRING *db= &lex->name;
#ifdef HAVE_REPLICATION
if (thd->slave_thread)
{
@@ -4982,7 +5120,7 @@ end_with_restore_list:
}
}
#endif
- if (check_db_name(db))
+ if (check_db_name((LEX_STRING*) db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
break;
@@ -5002,32 +5140,8 @@ end_with_restore_list:
}
case SQLCOM_ALTER_DB:
{
- LEX_STRING *db= &lex->name;
- if (check_db_name(db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
- break;
- }
- /*
- If in a slave thread :
- ALTER DATABASE DB may not be preceded by USE DB.
- For that reason, maybe db_ok() in sql/slave.cc did not check the
- do_db/ignore_db. And as this query involves no tables, tables_ok()
- above was not called. So we have to check rules again here.
- */
-#ifdef HAVE_REPLICATION
- if (thd->slave_thread)
- {
- rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
- if (!rpl_filter->db_ok(db->str) ||
- !rpl_filter->db_ok_with_wild_table(db->str))
- {
- my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE), MYF(0));
- break;
- }
- }
-#endif
- if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0))
+ LEX_CSTRING *db= &lex->name;
+ if (prepare_db_action(thd, ALTER_ACL, db))
break;
WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL)
res= mysql_alter_db(thd, db->str, &lex->create_info);
@@ -5036,19 +5150,19 @@ end_with_restore_list:
case SQLCOM_SHOW_CREATE_DB:
{
char db_name_buff[NAME_LEN+1];
- LEX_STRING db_name;
+ LEX_CSTRING db_name;
DBUG_EXECUTE_IF("4x_server_emul",
my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;);
db_name.str= db_name_buff;
db_name.length= lex->name.length;
- strmov(db_name.str, lex->name.str);
+ strmov(db_name_buff, lex->name.str);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error;
#endif /* WITH_WSREP */
- if (check_db_name(&db_name))
+ if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
break;
@@ -5104,13 +5218,13 @@ end_with_restore_list:
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error;
#endif /* WITH_WSREP */
- res= Events::show_create_event(thd, lex->spname->m_db,
- lex->spname->m_name);
+ res= Events::show_create_event(thd, &lex->spname->m_db,
+ &lex->spname->m_name);
break;
case SQLCOM_DROP_EVENT:
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (!(res= Events::drop_event(thd,
- lex->spname->m_db, lex->spname->m_name,
+ &lex->spname->m_db, &lex->spname->m_name,
lex->if_exists())))
my_ok(thd);
break;
@@ -5636,120 +5750,7 @@ end_with_restore_list:
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
{
- uint namelen;
- char *name;
-
- DBUG_ASSERT(lex->sphead != 0);
- DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
- /*
- Verify that the database name is allowed, optionally
- lowercase it.
- */
- if (check_db_name(&lex->sphead->m_db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
- goto error;
- }
-
- if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
- NULL, NULL, 0, 0))
- goto error;
-
- /* Checking the drop permissions if CREATE OR REPLACE is used */
- if (lex->create_info.or_replace())
- {
- if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str,
- lex->spname->m_name.str,
- lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
- goto error;
- }
-
- name= lex->sphead->name(&namelen);
-#ifdef HAVE_DLOPEN
- if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
- {
- udf_func *udf = find_udf(name, namelen);
-
- if (udf)
- {
- my_error(ER_UDF_EXISTS, MYF(0), name);
- goto error;
- }
- }
-#endif
-
- if (sp_process_definer(thd))
- goto error;
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
- if (!sp_create_routine(thd, lex->sphead->m_type, lex->sphead))
- {
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /* only add privileges if really neccessary */
-
- Security_context security_context;
- bool restore_backup_context= false;
- Security_context *backup= NULL;
- LEX_USER *definer= thd->lex->definer;
- /*
- We're going to issue an implicit GRANT statement so we close all
- open tables. We have to keep metadata locks as this ensures that
- this statement is atomic against concurent FLUSH TABLES WITH READ
- LOCK. Deadlocks which can arise due to fact that this implicit
- statement takes metadata locks should be detected by a deadlock
- detector in MDL subsystem and reported as errors.
-
- No need to commit/rollback statement transaction, it's not started.
-
- TODO: Long-term we should either ensure that implicit GRANT statement
- is written into binary log as a separate statement or make both
- creation of routine and implicit GRANT parts of one fully atomic
- statement.
- */
- DBUG_ASSERT(thd->transaction.stmt.is_empty());
- close_thread_tables(thd);
- /*
- Check if the definer exists on slave,
- then use definer privilege to insert routine privileges to mysql.procs_priv.
-
- For current user of SQL thread has GLOBAL_ACL privilege,
- which doesn't any check routine privileges,
- so no routine privilege record will insert into mysql.procs_priv.
- */
- if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str))
- {
- security_context.change_security_context(thd,
- &thd->lex->definer->user,
- &thd->lex->definer->host,
- &thd->lex->sphead->m_db,
- &backup);
- restore_backup_context= true;
- }
-
- if (sp_automatic_privileges && !opt_noacl &&
- check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
- lex->sphead->m_db.str, name,
- lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
- {
- if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
- lex->sql_command == SQLCOM_CREATE_PROCEDURE))
- push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL, ER_THD(thd, ER_PROC_AUTO_GRANT_FAIL));
- thd->clear_error();
- }
-
- /*
- Restore current user with GLOBAL_ACL privilege of SQL thread
- */
- if (restore_backup_context)
- {
- DBUG_ASSERT(thd->slave_thread == 1);
- thd->security_ctx->restore_security_context(thd, backup);
- }
-
-#endif
- }
- else
+ if (mysql_create_routine(thd, lex))
goto error;
my_ok(thd);
break; /* break super switch */
@@ -5777,9 +5778,15 @@ end_with_restore_list:
if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
&thd->sp_proc_cache, TRUE)))
{
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
- lex->spname->m_qname.str);
- goto error;
+ /*
+ sp_find_routine can have issued an ER_SP_RECURSION_LIMIT error.
+ Send message ER_SP_DOES_NOT_EXIST only if procedure is not found in
+ cache.
+ */
+ if (!sp_cache_lookup(&thd->sp_proc_cache, lex->spname))
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
+ ErrConvDQName(lex->spname).ptr());
+ goto error;
}
else
{
@@ -5838,11 +5845,11 @@ end_with_restore_list:
break;
case SP_KEY_NOT_FOUND:
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
default:
my_error(ER_SP_CANT_ALTER, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
}
break;
@@ -5895,8 +5902,8 @@ end_with_restore_list:
enum stored_procedure_type type;
type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
- char *db= lex->spname->m_db.str;
- char *name= lex->spname->m_name.str;
+ const char *db= lex->spname->m_db.str;
+ const char *name= lex->spname->m_name.str;
if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
@@ -5949,17 +5956,18 @@ end_with_restore_list:
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER_THD(thd, ER_SP_DOES_NOT_EXIST),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex),
+ ErrConvDQName(lex->spname).ptr());
if (!res)
my_ok(thd);
break;
}
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
default:
my_error(ER_SP_DROP_FAILED, MYF(0),
- SP_COM_STRING(lex), lex->spname->m_qname.str);
+ SP_COM_STRING(lex), ErrConvDQName(lex->spname).ptr());
goto error;
}
break;
@@ -6026,10 +6034,10 @@ end_with_restore_list:
{
/*
Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands
- as specified through the thd->lex->create_view_mode flag.
+ as specified through the thd->lex->create_view->mode flag.
*/
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
- res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
+ res= mysql_create_view(thd, first_table, thd->lex->create_view->mode);
break;
}
case SQLCOM_DROP_VIEW:
@@ -6202,9 +6210,11 @@ end_with_restore_list:
case SQLCOM_REPAIR:
case SQLCOM_TRUNCATE:
case SQLCOM_ALTER_TABLE:
- thd->query_plan_flags|= QPLAN_ADMIN;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
/* fall through */
+ case SQLCOM_ALTER_SEQUENCE:
+ thd->query_plan_flags|= QPLAN_ADMIN;
+ /* fall through */
case SQLCOM_SIGNAL:
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
@@ -7023,6 +7033,15 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
thd->security_ctx= sctx;
+ if (table_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ want_access= ((table_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
+
if (check_access(thd, want_access, table_ref->get_db_name(),
&table_ref->grant.privilege,
&table_ref->grant.m_internal,
@@ -7040,7 +7059,8 @@ deny:
bool
-check_routine_access(THD *thd, ulong want_access,char *db, char *name,
+check_routine_access(THD *thd, ulong want_access, const char *db,
+ const char *name,
bool is_proc, bool no_errors)
{
TABLE_LIST tables[1];
@@ -7213,8 +7233,8 @@ bool check_fk_parent_table_access(THD *thd,
TABLE_LIST parent_table;
bool is_qualified_table_name;
Foreign_key *fk_key= (Foreign_key *)key;
- LEX_STRING db_name;
- LEX_STRING table_name= { fk_key->ref_table.str,
+ LEX_CSTRING db_name;
+ LEX_CSTRING table_name= { fk_key->ref_table.str,
fk_key->ref_table.length };
const ulong privileges= (SELECT_ACL | INSERT_ACL | UPDATE_ACL |
DELETE_ACL | REFERENCES_ACL);
@@ -7230,12 +7250,13 @@ bool check_fk_parent_table_access(THD *thd,
if (fk_key->ref_db.str)
{
is_qualified_table_name= true;
- db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
- fk_key->ref_db.length+1);
+ if (!(db_name.str= (char *) thd->memdup(fk_key->ref_db.str,
+ fk_key->ref_db.length+1)))
+ return true;
db_name.length= fk_key->ref_db.length;
// Check if database name is valid or not.
- if (fk_key->ref_db.str && check_db_name(&db_name))
+ if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
return true;
@@ -7245,11 +7266,14 @@ bool check_fk_parent_table_access(THD *thd,
{
if (!thd->db)
{
- db_name.str= (char *) thd->memdup(create_db, strlen(create_db)+1);
+ DBUG_ASSERT(create_db);
db_name.length= strlen(create_db);
+ if (!(db_name.str= (char *) thd->memdup(create_db,
+ db_name.length+1)))
+ return true;
is_qualified_table_name= true;
- if(create_db && check_db_name(&db_name))
+ if (check_db_name((LEX_STRING*) &db_name))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
return true;
@@ -7267,10 +7291,11 @@ bool check_fk_parent_table_access(THD *thd,
// if lower_case_table_names is set then convert tablename to lower case.
if (lower_case_table_names)
{
- table_name.str= (char *) thd->memdup(fk_key->ref_table.str,
- fk_key->ref_table.length+1);
- table_name.length= my_casedn_str(files_charset_info, table_name.str);
- db_name.length = my_casedn_str(files_charset_info, db_name.str);
+ char *name;
+ table_name.str= name= (char *) thd->memdup(fk_key->ref_table.str,
+ fk_key->ref_table.length+1);
+ table_name.length= my_casedn_str(files_charset_info, name);
+ db_name.length= my_casedn_str(files_charset_info, (char*) db_name.str);
}
parent_table.init_one_table(db_name.str, db_name.length,
@@ -7525,18 +7550,21 @@ mysql_init_select(LEX *lex)
*/
bool
-mysql_new_select(LEX *lex, bool move_down)
+mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex)
{
- SELECT_LEX *select_lex;
THD *thd= lex->thd;
+ bool new_select= select_lex == NULL;
DBUG_ENTER("mysql_new_select");
- if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
- DBUG_RETURN(1);
- select_lex->select_number= ++thd->select_number;
- select_lex->parent_lex= lex; /* Used in init_query. */
- select_lex->init_query();
- select_lex->init_select();
+ if (new_select)
+ {
+ if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
+ select_lex->select_number= ++thd->select_number;
+ select_lex->parent_lex= lex; /* Used in init_query. */
+ select_lex->init_query();
+ select_lex->init_select();
+ }
lex->nest_level++;
if (lex->nest_level > (int) MAX_SELECT_NESTING)
{
@@ -7607,7 +7635,8 @@ mysql_new_select(LEX *lex, bool move_down)
unit->first_select()->context.outer_context;
}
- select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
+ if (new_select)
+ select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
lex->current_select= select_lex;
/*
in subquery is SELECT query and we allow resolution of names in SELECT
@@ -7631,7 +7660,7 @@ void create_select_for_variable(const char *var_name)
{
THD *thd;
LEX *lex;
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
Item *var;
char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end;
DBUG_ENTER("create_select_for_variable");
@@ -7640,13 +7669,13 @@ void create_select_for_variable(const char *var_name)
lex= thd->lex;
mysql_init_select(lex);
lex->sql_command= SQLCOM_SELECT;
- tmp.str= (char*) var_name;
+ tmp.str= var_name;
tmp.length=strlen(var_name);
/*
We set the name of Item to @@session.var_name because that then is used
as the column name in the output.
*/
- if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_str)))
+ if ((var= get_system_var(thd, OPT_SESSION, tmp, null_clex_str)))
{
end= strxmov(buff, "@@session.", var_name, NullS);
var->set_name(thd, buff, end-buff, system_charset_info);
@@ -7739,7 +7768,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
(longlong) thd->thread_id, is_autocommit,
thd->wsrep_retry_counter,
thd->variables.wsrep_retry_autocommit, thd->query());
- my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction");
+ my_message(ER_LOCK_DEADLOCK, "wsrep aborted transaction", MYF(0));
thd->killed= NOT_KILLED;
thd->wsrep_conflict_state= NO_CONFLICT;
if (thd->wsrep_conflict_state != REPLAYING)
@@ -8013,7 +8042,7 @@ bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *item,bool asc)
TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
Table_ident *table,
- LEX_STRING *alias,
+ LEX_CSTRING *alias,
ulong table_options,
thr_lock_type lock_type,
enum_mdl_type mdl_type,
@@ -8023,7 +8052,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
register TABLE_LIST *ptr;
TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */
- char *alias_str;
+ const char *alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
@@ -8038,7 +8067,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
if (table->is_derived_table() == FALSE && table->db.str &&
- check_db_name(&table->db))
+ check_db_name((LEX_STRING*) &table->db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
DBUG_RETURN(0);
@@ -8073,9 +8102,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (lower_case_table_names)
{
if (table->table.length)
- table->table.length= my_casedn_str(files_charset_info, table->table.str);
+ table->table.length= my_casedn_str(files_charset_info,
+ (char*) table->table.str);
if (ptr->db_length && ptr->db != any_db)
- ptr->db_length= my_casedn_str(files_charset_info, ptr->db);
+ ptr->db_length= my_casedn_str(files_charset_info, (char*) ptr->db);
}
ptr->table_name=table->table.str;
@@ -8085,6 +8115,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
/* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
ptr->force_index= MY_TEST(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= MY_TEST(table_options & TL_OPTION_IGNORE_LEAVES);
+ ptr->sequence= MY_TEST(table_options & TL_OPTION_SEQUENCE);
ptr->derived= table->sel;
if (!ptr->derived && is_infoschema_db(ptr->db, ptr->db_length))
{
@@ -8125,8 +8156,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->cacheable_table= !table->is_derived_table();
ptr->index_hints= index_hints_arg;
ptr->option= option ? option->str : 0;
- /* check that used name is unique */
- if (lock_type != TL_IGNORE)
+ /* check that used name is unique. Sequences are ignored */
+ if (lock_type != TL_IGNORE && !ptr->sequence)
{
TABLE_LIST *first_table= table_list.first;
if (lex->sql_command == SQLCOM_CREATE_VIEW)
@@ -8136,7 +8167,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
tables=tables->next_local)
{
if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
- !strcmp(ptr->db, tables->db))
+ !strcmp(ptr->db, tables->db) && ! tables->sequence)
{
my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
@@ -8144,7 +8175,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
}
/* Store the table reference preceding the current one. */
- if (table_list.elements > 0)
+ if (table_list.elements > 0 && !ptr->sequence)
{
/*
table_list.next points to the last inserted TABLE_LIST->next_local'
@@ -8169,8 +8200,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
Notice that as a side effect here we set the next_local field of the
previous table reference to 'ptr'. Here we also add one element to the
list 'table_list'.
+ We don't store sequences into the local list to hide them from INSERT
+ and SELECT.
*/
- table_list.link_in_list(ptr, &ptr->next_local);
+ if (!ptr->sequence)
+ table_list.link_in_list(ptr, &ptr->next_local);
ptr->next_name_resolution_table= NULL;
#ifdef WITH_PARTITION_STORAGE_ENGINE
ptr->partition_names= partition_names;
@@ -8414,8 +8448,8 @@ void st_select_lex::prepare_add_window_spec(THD *thd)
}
bool st_select_lex::add_window_def(THD *thd,
- LEX_STRING *win_name,
- LEX_STRING *win_ref,
+ LEX_CSTRING *win_name,
+ LEX_CSTRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame)
@@ -8437,7 +8471,7 @@ bool st_select_lex::add_window_def(THD *thd,
}
bool st_select_lex::add_window_spec(THD *thd,
- LEX_STRING *win_ref,
+ LEX_CSTRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame)
@@ -8538,7 +8572,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
fake_select_lex->nest_level_base= first_select()->nest_level_base;
fake_select_lex->nest_level=first_select()->nest_level;
- if (!is_union())
+ if (!is_unit_op())
{
/*
This works only for
@@ -9566,7 +9600,7 @@ void get_default_definer(THD *thd, LEX_USER *definer, bool role)
if (role)
{
definer->user.str= const_cast<char*>(sctx->priv_role);
- definer->host= empty_lex_str;
+ definer->host= empty_clex_str;
}
else
{
@@ -9623,7 +9657,8 @@ LEX_USER *create_default_definer(THD *thd, bool role)
- On error, return 0.
*/
-LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
+LEX_USER *create_definer(THD *thd, LEX_CSTRING *user_name,
+ LEX_CSTRING *host_name)
{
LEX_USER *definer;
@@ -9657,7 +9692,7 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
The function is not used in existing code but can be useful later?
*/
-bool check_string_byte_length(LEX_STRING *str, uint err_msg,
+bool check_string_byte_length(LEX_CSTRING *str, uint err_msg,
uint max_byte_length)
{
if (str->length <= max_byte_length)
@@ -9687,7 +9722,7 @@ bool check_string_byte_length(LEX_STRING *str, uint err_msg,
*/
-bool check_string_char_length(LEX_STRING *str, uint err_msg,
+bool check_string_char_length(LEX_CSTRING *str, uint err_msg,
uint max_char_length, CHARSET_INFO *cs,
bool no_error)
{
@@ -9706,7 +9741,7 @@ bool check_string_char_length(LEX_STRING *str, uint err_msg,
}
-bool check_ident_length(LEX_STRING *ident)
+bool check_ident_length(LEX_CSTRING *ident)
{
if (check_string_char_length(ident, 0, NAME_CHAR_LEN, system_charset_info, 1))
{
@@ -9816,7 +9851,7 @@ int error_if_data_home_dir(const char *path, const char *what)
has invalid symbols
*/
-bool check_host_name(LEX_STRING *str)
+bool check_host_name(LEX_CSTRING *str)
{
const char *name= str->str;
const char *end= str->str + str->length;
@@ -9839,6 +9874,7 @@ bool check_host_name(LEX_STRING *str)
extern int MYSQLparse(THD *thd); // from sql_yacc.cc
+extern int ORAparse(THD *thd); // from sql_yacc_ora.cc
/**
@@ -9898,7 +9934,10 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
/* Parse the query. */
- bool mysql_parse_status= MYSQLparse(thd) != 0;
+ bool mysql_parse_status=
+ ((thd->variables.sql_mode & MODE_ORACLE) ?
+ ORAparse(thd) :
+ MYSQLparse(thd)) != 0;
/*
Check that if MYSQLparse() failed either thd->is_error() is set, or an
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index eedb74df959..bf241d04e7b 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -70,19 +70,19 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
enum enum_schema_tables schema_table_idx);
void get_default_definer(THD *thd, LEX_USER *definer, bool role);
LEX_USER *create_default_definer(THD *thd, bool role);
-LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
+LEX_USER *create_definer(THD *thd, LEX_CSTRING *user_name, LEX_CSTRING *host_name);
LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock=true);
bool sp_process_definer(THD *thd);
-bool check_string_byte_length(LEX_STRING *str, uint err_msg,
+bool check_string_byte_length(LEX_CSTRING *str, uint err_msg,
uint max_byte_length);
-bool check_string_char_length(LEX_STRING *str, uint err_msg,
+bool check_string_char_length(LEX_CSTRING *str, uint err_msg,
uint max_char_length, CHARSET_INFO *cs,
bool no_error);
-bool check_ident_length(LEX_STRING *ident);
+bool check_ident_length(LEX_CSTRING *ident);
CHARSET_INFO* merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl);
CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs);
-bool check_host_name(LEX_STRING *str);
-bool check_identifier_name(LEX_STRING *str, uint max_char_length,
+bool check_host_name(LEX_CSTRING *str);
+bool check_identifier_name(LEX_CSTRING *str, uint max_char_length,
uint err_code, const char *param_for_err_msg);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
bool sqlcom_can_generate_row_events(const THD *thd);
@@ -93,7 +93,7 @@ void mysql_init_select(LEX *lex);
void mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state, bool is_com_multi,
bool is_next_command);
-bool mysql_new_select(LEX *lex, bool move_down);
+bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
void create_select_for_variable(const char *var_name);
void create_table_set_open_action_and_adjust_tables(LEX *lex);
void mysql_init_multi_delete(LEX *lex);
@@ -136,12 +136,12 @@ extern const LEX_STRING command_name[];
extern uint server_command_flags[];
/* Inline functions */
-inline bool check_identifier_name(LEX_STRING *str, uint err_code)
+inline bool check_identifier_name(LEX_CSTRING *str, uint err_code)
{
return check_identifier_name(str, NAME_CHAR_LEN, err_code, "");
}
-inline bool check_identifier_name(LEX_STRING *str)
+inline bool check_identifier_name(LEX_CSTRING *str)
{
return check_identifier_name(str, NAME_CHAR_LEN, 0, "");
}
@@ -150,7 +150,8 @@ inline bool check_identifier_name(LEX_STRING *str)
bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables);
bool check_single_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables, bool no_errors);
-bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
+bool check_routine_access(THD *thd,ulong want_access,const char *db,
+ const char *name,
bool is_proc, bool no_errors);
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
@@ -164,8 +165,8 @@ inline bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables
inline bool check_single_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables, bool no_errors)
{ return false; }
-inline bool check_routine_access(THD *thd,ulong want_access,char *db,
- char *name, bool is_proc, bool no_errors)
+inline bool check_routine_access(THD *thd,ulong want_access, const char *db,
+ const char *name, bool is_proc, bool no_errors)
{ return false; }
inline bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
{
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 6d202477b76..c3417ce4f08 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -177,15 +177,15 @@ Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs)
@retval false String not found
*/
-static bool is_name_in_list(char *name, List<char> list_names)
+static bool is_name_in_list(const char *name, List<const char> list_names)
{
- List_iterator<char> names_it(list_names);
+ List_iterator<const char> names_it(list_names);
uint num_names= list_names.elements;
uint i= 0;
do
{
- char *list_name= names_it++;
+ const char *list_name= names_it++;
if (!(my_strcasecmp(system_charset_info, name, list_name)))
return TRUE;
} while (++i < num_names);
@@ -261,7 +261,7 @@ bool partition_default_handling(THD *thd, TABLE *table, partition_info *part_inf
> 0 Error code
*/
-int get_parts_for_update(const uchar *old_data, uchar *new_data,
+int get_parts_for_update(const uchar *old_data, const uchar *new_data,
const uchar *rec0, partition_info *part_info,
uint32 *old_part_id, uint32 *new_part_id,
longlong *new_func_value)
@@ -463,8 +463,8 @@ static bool set_up_field_array(THD *thd, TABLE *table,
{
if (!is_sub_part && part_info->column_list)
{
- List_iterator<char> it(part_info->part_field_list);
- char *field_name;
+ List_iterator<const char> it(part_info->part_field_list);
+ const char *field_name;
DBUG_ASSERT(num_fields == part_info->part_field_list.elements);
inx= 0;
@@ -473,7 +473,7 @@ static bool set_up_field_array(THD *thd, TABLE *table,
field_name= it++;
if (!my_strcasecmp(system_charset_info,
field_name,
- field->field_name))
+ field->field_name.str))
break;
} while (++inx < num_fields);
if (inx == num_fields)
@@ -758,14 +758,14 @@ static void clear_field_flag(TABLE *table)
*/
-static bool handle_list_of_fields(THD *thd, List_iterator<char> it,
+static bool handle_list_of_fields(THD *thd, List_iterator<const char> it,
TABLE *table,
partition_info *part_info,
bool is_sub_part)
{
Field *field;
bool result;
- char *field_name;
+ const char *field_name;
bool is_list_empty= TRUE;
DBUG_ENTER("handle_list_of_fields");
@@ -1590,7 +1590,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
set_linear_hash_mask(part_info, part_info->num_subparts);
if (part_info->list_of_subpart_fields)
{
- List_iterator<char> it(part_info->subpart_field_list);
+ List_iterator<const char> it(part_info->subpart_field_list);
if (unlikely(handle_list_of_fields(thd, it, table, part_info, TRUE)))
goto end;
}
@@ -1617,7 +1617,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
set_linear_hash_mask(part_info, part_info->num_parts);
if (part_info->list_of_part_fields)
{
- List_iterator<char> it(part_info->part_field_list);
+ List_iterator<const char> it(part_info->part_field_list);
if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE)))
goto end;
}
@@ -1639,7 +1639,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
const char *error_str;
if (part_info->column_list)
{
- List_iterator<char> it(part_info->part_field_list);
+ List_iterator<const char> it(part_info->part_field_list);
if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE)))
goto end;
}
@@ -1736,11 +1736,11 @@ end:
ALTER TABLE commands. Finally it is used for SHOW CREATE TABLES.
*/
-static int add_part_field_list(THD *thd, String *str, List<char> field_list)
+static int add_part_field_list(THD *thd, String *str, List<const char> field_list)
{
int err= 0;
const char *field_name;
- List_iterator<char> part_it(field_list);
+ List_iterator<const char> part_it(field_list);
err+= str->append('(');
while ((field_name= part_it++))
@@ -1971,7 +1971,7 @@ error:
NULL No field found
*/
-static Create_field* get_sql_field(char *field_name,
+static Create_field* get_sql_field(const char *field_name,
Alter_info *alter_info)
{
List_iterator<Create_field> it(alter_info->create_list);
@@ -1981,7 +1981,7 @@ static Create_field* get_sql_field(char *field_name,
while ((sql_field= it++))
{
if (!(my_strcasecmp(system_charset_info,
- sql_field->field_name,
+ sql_field->field_name.str,
field_name)))
{
DBUG_RETURN(sql_field);
@@ -1998,7 +1998,7 @@ static int add_column_list_values(String *str, partition_info *part_info,
{
int err= 0;
uint i;
- List_iterator<char> it(part_info->part_field_list);
+ List_iterator<const char> it(part_info->part_field_list);
uint num_elements= part_info->part_field_list.elements;
bool use_parenthesis= (part_info->part_type == LIST_PARTITION &&
part_info->num_columns > 1U);
@@ -2008,7 +2008,7 @@ static int add_column_list_values(String *str, partition_info *part_info,
for (i= 0; i < num_elements; i++)
{
part_column_list_val *col_val= &list_value->col_val_array[i];
- char *field_name= it++;
+ const char *field_name= it++;
if (col_val->max_value)
err+= str->append(STRING_WITH_LEN("MAXVALUE"));
else if (col_val->null_value)
@@ -2040,8 +2040,8 @@ static int add_column_list_values(String *str, partition_info *part_info,
my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
return 1;
}
- if (check_part_field(sql_field->sql_type,
- sql_field->field_name,
+ if (check_part_field(sql_field->real_field_type(),
+ sql_field->field_name.str,
&result_type,
&need_cs_check))
return 1;
@@ -2055,7 +2055,7 @@ static int add_column_list_values(String *str, partition_info *part_info,
Field *field= part_info->part_field_array[i];
result_type= field->result_type();
if (check_part_field(field->real_type(),
- field->field_name,
+ field->field_name.str,
&result_type,
&need_cs_check))
return 1;
@@ -6544,7 +6544,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
Alter_info *alter_info,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
- char *db,
+ const char *db,
const char *table_name)
{
/* Set-up struct used to write frm files */
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index 2d0ec788332..b0dede7487e 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -85,7 +85,7 @@ bool check_reorganise_list(partition_info *new_part_info,
partition_info *old_part_info,
List<char> list_part_names);
handler *get_ha_partition(partition_info *part_info);
-int get_parts_for_update(const uchar *old_data, uchar *new_data,
+int get_parts_for_update(const uchar *old_data, const uchar *new_data,
const uchar *rec0, partition_info *part_info,
uint32 *old_part_id, uint32 *new_part_id,
longlong *func_value);
@@ -257,7 +257,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
Alter_info *alter_info,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
- char *db,
+ const char *db,
const char *table_name);
bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
enum partition_state part_state);
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index f5e47206963..ed330bcc7b9 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -371,16 +371,14 @@ static bool exchange_name_with_ddl_log(THD *thd,
/* call rename table from table to tmp-name */
DBUG_EXECUTE_IF("exchange_partition_fail_3",
my_error(ER_ERROR_ON_RENAME, MYF(0),
- name, tmp_name, 0, "n/a");
+ name, tmp_name, 0);
error_set= TRUE;
goto err_rename;);
DBUG_EXECUTE_IF("exchange_partition_abort_3", DBUG_SUICIDE(););
if (file->ha_rename_table(name, tmp_name))
{
- char errbuf[MYSYS_STRERROR_SIZE];
- my_strerror(errbuf, sizeof(errbuf), my_errno);
my_error(ER_ERROR_ON_RENAME, MYF(0), name, tmp_name,
- my_errno, errbuf);
+ my_errno);
error_set= TRUE;
goto err_rename;
}
@@ -392,16 +390,13 @@ static bool exchange_name_with_ddl_log(THD *thd,
/* call rename table from partition to table */
DBUG_EXECUTE_IF("exchange_partition_fail_5",
my_error(ER_ERROR_ON_RENAME, MYF(0),
- from_name, name, 0, "n/a");
+ from_name, name, 0);
error_set= TRUE;
goto err_rename;);
DBUG_EXECUTE_IF("exchange_partition_abort_5", DBUG_SUICIDE(););
if (file->ha_rename_table(from_name, name))
{
- char errbuf[MYSYS_STRERROR_SIZE];
- my_strerror(errbuf, sizeof(errbuf), my_errno);
- my_error(ER_ERROR_ON_RENAME, MYF(0), from_name, name,
- my_errno, errbuf);
+ my_error(ER_ERROR_ON_RENAME, MYF(0), from_name, name, my_errno);
error_set= TRUE;
goto err_rename;
}
@@ -413,16 +408,13 @@ static bool exchange_name_with_ddl_log(THD *thd,
/* call rename table from tmp-nam to partition */
DBUG_EXECUTE_IF("exchange_partition_fail_7",
my_error(ER_ERROR_ON_RENAME, MYF(0),
- tmp_name, from_name, 0, "n/a");
+ tmp_name, from_name, 0);
error_set= TRUE;
goto err_rename;);
DBUG_EXECUTE_IF("exchange_partition_abort_7", DBUG_SUICIDE(););
if (file->ha_rename_table(tmp_name, from_name))
{
- char errbuf[MYSYS_STRERROR_SIZE];
- my_strerror(errbuf, sizeof(errbuf), my_errno);
- my_error(ER_ERROR_ON_RENAME, MYF(0), tmp_name, from_name,
- my_errno, errbuf);
+ my_error(ER_ERROR_ON_RENAME, MYF(0), tmp_name, from_name, my_errno);
error_set= TRUE;
goto err_rename;
}
@@ -491,7 +483,7 @@ bool Sql_cmd_alter_table_exchange_partition::
TABLE_LIST *swap_table_list;
handlerton *table_hton;
partition_element *part_elem;
- char *partition_name;
+ const char *partition_name;
char temp_name[FN_REFLEN+1];
char part_file_name[2*FN_REFLEN+1];
char swap_file_name[FN_REFLEN+1];
@@ -579,7 +571,7 @@ bool Sql_cmd_alter_table_exchange_partition::
swap_table_list->table_name,
"", 0);
/* create a unique temp name #sqlx-nnnn_nnnn, x for eXchange */
- my_snprintf(temp_name, sizeof(temp_name), "%sx-%lx_%lx",
+ my_snprintf(temp_name, sizeof(temp_name), "%sx-%lx_%llx",
tmp_file_prefix, current_pid, thd->thread_id);
if (lower_case_table_names)
my_casedn_str(files_charset_info, temp_name);
@@ -808,11 +800,11 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
Prune all, but named partitions,
to avoid excessive calls to external_lock().
*/
- List_iterator<char> partition_names_it(alter_info->partition_names);
+ List_iterator<const char> partition_names_it(alter_info->partition_names);
uint num_names= alter_info->partition_names.elements;
for (i= 0; i < num_names; i++)
{
- char *partition_name= partition_names_it++;
+ const char *partition_name= partition_names_it++;
String *str_partition_name= new (thd->mem_root)
String(partition_name, system_charset_info);
if (!str_partition_name)
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 97ef24f44ed..ab829c093f6 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -296,10 +296,10 @@ public:
sys_var_pluginvar *cast_pluginvar() { return this; }
uchar* real_value_ptr(THD *thd, enum_var_type type);
TYPELIB* plugin_var_typelib(void);
- uchar* do_value_ptr(THD *thd, enum_var_type type, const LEX_STRING *base);
- uchar* session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar* do_value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base);
+ uchar* session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return do_value_ptr(thd, OPT_SESSION, base); }
- uchar* global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar* global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return do_value_ptr(thd, OPT_GLOBAL, base); }
uchar *default_value_ptr(THD *thd)
{ return do_value_ptr(thd, OPT_DEFAULT, 0); }
@@ -370,7 +370,7 @@ bool check_valid_path(const char *path, size_t len)
return prefix < len;
}
-static void fix_dl_name(MEM_ROOT *root, LEX_STRING *dl)
+static void fix_dl_name(MEM_ROOT *root, LEX_CSTRING *dl)
{
const size_t so_ext_len= sizeof(SO_EXT) - 1;
if (my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len,
@@ -450,7 +450,7 @@ static int item_val_real(struct st_mysql_value *value, double *buf)
#ifdef HAVE_DLOPEN
-static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl)
+static struct st_plugin_dl *plugin_dl_find(const LEX_CSTRING *dl)
{
uint i;
struct st_plugin_dl *tmp;
@@ -506,7 +506,7 @@ static void free_plugin_mem(struct st_plugin_dl *p)
if (p->handle)
dlclose(p->handle);
#endif
- my_free(p->dl.str);
+ my_free(const_cast<char*>(p->dl.str));
if (p->allocated)
my_free(p->plugins);
}
@@ -726,7 +726,7 @@ static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
}
#endif /* HAVE_DLOPEN */
-static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
+static st_plugin_dl *plugin_dl_add(const LEX_CSTRING *dl, int report)
{
#ifdef HAVE_DLOPEN
char dlpath[FN_REFLEN];
@@ -745,7 +745,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
plugin directory are used (to make this even remotely secure).
*/
if (check_valid_path(dl->str, dl->length) ||
- check_string_char_length((LEX_STRING *) dl, 0, NAME_CHAR_LEN,
+ check_string_char_length((LEX_CSTRING *) dl, 0, NAME_CHAR_LEN,
system_charset_info, 1) ||
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
{
@@ -838,10 +838,12 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
static_cast<int>(plugin_dl.dl.length));
goto ret;
}
- plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
- files_charset_info, dl->str, dl->length, system_charset_info,
- &dummy_errors);
- plugin_dl.dl.str[plugin_dl.dl.length]= 0;
+ plugin_dl.dl.length= copy_and_convert((char*) plugin_dl.dl.str,
+ plugin_dl.dl.length,
+ files_charset_info, dl->str,
+ dl->length, system_charset_info,
+ &dummy_errors);
+ ((char*) plugin_dl.dl.str)[plugin_dl.dl.length]= 0;
/* Add this dll to array */
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
{
@@ -884,7 +886,8 @@ static void plugin_dl_del(struct st_plugin_dl *plugin_dl)
}
-static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type)
+static struct st_plugin_int *plugin_find_internal(const LEX_CSTRING *name,
+ int type)
{
uint i;
DBUG_ENTER("plugin_find_internal");
@@ -911,7 +914,7 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty
}
-static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
+static SHOW_COMP_OPTION plugin_status(const LEX_CSTRING *name, int type)
{
SHOW_COMP_OPTION rc= SHOW_OPTION_NO;
struct st_plugin_int *plugin;
@@ -928,7 +931,7 @@ static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type)
}
-bool plugin_is_ready(const LEX_STRING *name, int type)
+bool plugin_is_ready(const LEX_CSTRING *name, int type)
{
bool rc= FALSE;
if (plugin_status(name, type) == SHOW_OPTION_YES)
@@ -939,7 +942,7 @@ bool plugin_is_ready(const LEX_STRING *name, int type)
SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type)
{
- LEX_STRING plugin_name= { (char *) name, len };
+ LEX_CSTRING plugin_name= { name, len };
return plugin_status(&plugin_name, type);
}
@@ -1023,7 +1026,7 @@ plugin_ref plugin_lock(THD *thd, plugin_ref ptr)
}
-plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type)
+plugin_ref plugin_lock_by_name(THD *thd, const LEX_CSTRING *name, int type)
{
LEX *lex= thd ? thd->lex : 0;
plugin_ref rc= NULL;
@@ -1066,7 +1069,7 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
Requires that a write-lock is held on LOCK_system_variables_hash
*/
static bool plugin_add(MEM_ROOT *tmp_root,
- const LEX_STRING *name, LEX_STRING *dl, int report)
+ const LEX_CSTRING *name, LEX_CSTRING *dl, int report)
{
struct st_plugin_int tmp, *maybe_dupe;
struct st_maria_plugin *plugin;
@@ -1533,7 +1536,7 @@ int plugin_init(int *argc, char **argv, int flags)
MEM_ROOT tmp_root;
bool reaped_mandatory_plugin= false;
bool mandatory= true;
- LEX_STRING MyISAM= { C_STRING_WITH_LEN("MyISAM") };
+ LEX_CSTRING MyISAM= { STRING_WITH_LEN("MyISAM") };
DBUG_ENTER("plugin_init");
if (initialized)
@@ -1662,10 +1665,11 @@ int plugin_init(int *argc, char **argv, int flags)
char path[FN_REFLEN + 1];
build_table_filename(path, sizeof(path) - 1, "mysql", "plugin", reg_ext, 0);
char engine_name_buf[NAME_CHAR_LEN + 1];
- LEX_STRING maybe_myisam= { engine_name_buf, 0 };
- frm_type_enum frm_type= dd_frm_type(NULL, path, &maybe_myisam);
+ LEX_CSTRING maybe_myisam= { engine_name_buf, 0 };
+ bool is_sequence;
+ Table_type frm_type= dd_frm_type(NULL, path, &maybe_myisam, &is_sequence);
/* if mysql.plugin table is MyISAM - load it right away */
- if (frm_type == FRMTYPE_TABLE && !strcasecmp(maybe_myisam.str, "MyISAM"))
+ if (frm_type == TABLE_TYPE_NORMAL && !strcasecmp(maybe_myisam.str, "MyISAM"))
{
plugin_load(&tmp_root);
flags|= PLUGIN_INIT_SKIP_PLUGIN_TABLE;
@@ -1819,8 +1823,8 @@ static void plugin_load(MEM_ROOT *tmp_root)
get_field(tmp_root, table->field[0], &str_name);
get_field(tmp_root, table->field[1], &str_dl);
- LEX_STRING name= {(char *)str_name.ptr(), str_name.length()};
- LEX_STRING dl= {(char *)str_dl.ptr(), str_dl.length()};
+ LEX_CSTRING name= {str_name.ptr(), str_name.length()};
+ LEX_CSTRING dl= {str_dl.ptr(), str_dl.length()};
/*
there're no other threads running yet, so we don't need a mutex.
@@ -1883,14 +1887,16 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
mysql_mutex_lock(&LOCK_plugin);
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
name.str= 0; // load everything
- if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG))
+ if (plugin_add(tmp_root, (LEX_CSTRING*) &name, (LEX_CSTRING*) &dl,
+ REPORT_TO_LOG))
goto error;
}
else
{
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
mysql_mutex_lock(&LOCK_plugin);
- if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG))
+ if (plugin_add(tmp_root, (LEX_CSTRING*) &name, (LEX_CSTRING*) &dl,
+ REPORT_TO_LOG))
goto error;
}
mysql_mutex_unlock(&LOCK_plugin);
@@ -2059,7 +2065,7 @@ void plugin_shutdown(void)
That is, initialize it, and update mysql.plugin table
*/
-static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name,
+static bool finalize_install(THD *thd, TABLE *table, const LEX_CSTRING *name,
int *argc, char **argv)
{
struct st_plugin_int *tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
@@ -2113,12 +2119,12 @@ static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name,
return 0;
}
-bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
- const LEX_STRING *dl_arg)
+bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
+ const LEX_CSTRING *dl_arg)
{
TABLE_LIST tables;
TABLE *table;
- LEX_STRING dl= *dl_arg;
+ LEX_CSTRING dl= *dl_arg;
bool error;
int argc=orig_argc;
char **argv=orig_argv;
@@ -2178,7 +2184,7 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
struct st_maria_plugin *plugin;
for (plugin= plugin_dl->plugins; plugin->info; plugin++)
{
- LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
+ LEX_CSTRING str= { plugin->name, strlen(plugin->name) };
error|= finalize_install(thd, table, &str, &argc, argv);
}
}
@@ -2196,7 +2202,7 @@ err:
}
-static bool do_uninstall(THD *thd, TABLE *table, const LEX_STRING *name)
+static bool do_uninstall(THD *thd, TABLE *table, const LEX_CSTRING *name)
{
struct st_plugin_int *plugin;
mysql_mutex_assert_owner(&LOCK_plugin);
@@ -2252,12 +2258,12 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_STRING *name)
}
-bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
- const LEX_STRING *dl_arg)
+bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
+ const LEX_CSTRING *dl_arg)
{
TABLE *table;
TABLE_LIST tables;
- LEX_STRING dl= *dl_arg;
+ LEX_CSTRING dl= *dl_arg;
bool error= false;
DBUG_ENTER("mysql_uninstall_plugin");
@@ -2309,7 +2315,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
for (struct st_maria_plugin *plugin= plugin_dl->plugins;
plugin->info; plugin++)
{
- LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
+ LEX_CSTRING str= { plugin->name, strlen(plugin->name) };
error|= do_uninstall(thd, table, &str);
}
}
@@ -2425,7 +2431,7 @@ static bool plugin_dl_foreach_internal(THD *thd, st_plugin_dl *plugin_dl,
return 0;
}
-bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl,
+bool plugin_dl_foreach(THD *thd, const LEX_CSTRING *dl,
plugin_foreach_func *func, void *arg)
{
bool err= 0;
@@ -3394,7 +3400,7 @@ TYPELIB* sys_var_pluginvar::plugin_var_typelib(void)
uchar* sys_var_pluginvar::do_value_ptr(THD *thd, enum_var_type type,
- const LEX_STRING *base)
+ const LEX_CSTRING *base)
{
uchar* result;
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 7b89246a9f9..469ae5c88a3 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -90,7 +90,7 @@ struct st_ptr_backup {
struct st_plugin_dl
{
- LEX_STRING dl;
+ LEX_CSTRING dl;
void *handle;
struct st_maria_plugin *plugins;
st_ptr_backup *ptr_backup;
@@ -105,7 +105,7 @@ struct st_plugin_dl
struct st_plugin_int
{
- LEX_STRING name;
+ LEX_CSTRING name;
struct st_maria_plugin *plugin;
struct st_plugin_dl *plugin_dl;
st_ptr_backup *ptr_backup;
@@ -163,18 +163,18 @@ extern const char *plugin_maturity_names[];
extern int plugin_init(int *argc, char **argv, int init_flags);
extern void plugin_shutdown(void);
void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root);
-extern bool plugin_is_ready(const LEX_STRING *name, int type);
+extern bool plugin_is_ready(const LEX_CSTRING *name, int type);
#define my_plugin_lock_by_name(A,B,C) plugin_lock_by_name(A,B,C)
#define my_plugin_lock(A,B) plugin_lock(A,B)
extern plugin_ref plugin_lock(THD *thd, plugin_ref ptr);
-extern plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name,
+extern plugin_ref plugin_lock_by_name(THD *thd, const LEX_CSTRING *name,
int type);
extern void plugin_unlock(THD *thd, plugin_ref plugin);
extern void plugin_unlock_list(THD *thd, plugin_ref *list, uint count);
-extern bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
- const LEX_STRING *dl);
-extern bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
- const LEX_STRING *dl);
+extern bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
+ const LEX_CSTRING *dl);
+extern bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
+ const LEX_CSTRING *dl);
extern bool plugin_register_builtin(struct st_mysql_plugin *plugin);
extern void plugin_thdvar_init(THD *thd);
extern void plugin_thdvar_cleanup(THD *thd);
@@ -192,7 +192,7 @@ extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
int type, uint state_mask, void *arg);
extern void sync_dynamic_session_variables(THD* thd, bool global_lock);
-extern bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl,
+extern bool plugin_dl_foreach(THD *thd, const LEX_CSTRING *dl,
plugin_foreach_func *func, void *arg);
sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length,
diff --git a/sql/sql_plugin_compat.h b/sql/sql_plugin_compat.h
index 5c7bb620575..e0b184c9b2f 100644
--- a/sql/sql_plugin_compat.h
+++ b/sql/sql_plugin_compat.h
@@ -25,7 +25,7 @@
#define MIN_AUTHENTICATION_INTERFACE_VERSION 0x0100
struct MYSQL_SERVER_AUTH_INFO_0x0100 {
- char *user_name;
+ const char *user_name;
unsigned int user_name_length;
const char *auth_string;
unsigned long auth_string_length;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index f9da7e530cb..1095c6ead99 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -203,7 +203,7 @@ public:
void setup_set_params();
virtual Query_arena::Type type() const;
virtual void cleanup_stmt();
- bool set_name(LEX_STRING *name);
+ bool set_name(LEX_CSTRING *name);
inline void close_cursor() { delete cursor; cursor= 0; }
inline bool is_in_use() { return flags & (uint) IS_IN_USE; }
inline bool is_sql_prepare() const { return flags & (uint) IS_SQL_PREPARE; }
@@ -819,20 +819,6 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
#ifndef EMBEDDED_LIBRARY
/**
- Check whether this parameter data type is compatible with long data.
- Used to detect whether a long data stream has been supplied to a
- incompatible data type.
-*/
-inline bool is_param_long_data_type(Item_param *param)
-{
- enum_field_types field_type= param->field_type();
- return (((field_type >= MYSQL_TYPE_TINY_BLOB) &&
- (field_type <= MYSQL_TYPE_STRING)) ||
- field_type == MYSQL_TYPE_VARCHAR);
-}
-
-
-/**
Routines to assign parameters from data supplied by the client.
Update the parameter markers by reading data from the packet and
@@ -909,7 +895,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
type (the types are supplied at execute). Check that the
supplied type of placeholder can accept a data stream.
*/
- else if (! is_param_long_data_type(param))
+ else if (!param->type_handler()->is_param_long_data_type())
DBUG_RETURN(1);
if (acc.append(param))
@@ -957,7 +943,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
type (the types are supplied at execute). Check that the
supplied type of placeholder can accept a data stream.
*/
- else if (! is_param_long_data_type(param))
+ else if (!param->type_handler()->is_param_long_data_type())
DBUG_RETURN(1);
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
@@ -1510,6 +1496,7 @@ static bool mysql_test_delete(Prepared_statement *stmt,
uint table_count= 0;
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
+ bool delete_while_scanning;
DBUG_ENTER("mysql_test_delete");
if (delete_precheck(thd, table_list) ||
@@ -1538,7 +1525,8 @@ static bool mysql_test_delete(Prepared_statement *stmt,
DBUG_RETURN(mysql_prepare_delete(thd, table_list,
lex->select_lex.with_wild,
lex->select_lex.item_list,
- &lex->select_lex.where));
+ &lex->select_lex.where,
+ &delete_while_scanning));
error:
DBUG_RETURN(TRUE);
}
@@ -1963,8 +1951,7 @@ static int mysql_test_show_grants(Prepared_statement *stmt)
THD *thd= stmt->thd;
List<Item> fields;
- mysql_show_grants_get_fields(thd, &fields, "Grants for");
-
+ mysql_show_grants_get_fields(thd, &fields, STRING_WITH_LEN("Grants for"));
DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields));
}
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
@@ -2087,7 +2074,7 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
TABLE_LIST *tables= lex->query_tables;
- if (create_view_precheck(thd, tables, view, lex->create_view_mode))
+ if (create_view_precheck(thd, tables, view, lex->create_view->mode))
goto err;
/*
@@ -2287,7 +2274,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt,
{
if (!lex->result && !(lex->result= new (stmt->mem_root) select_send(thd)))
{
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(select_send));
+ my_error(ER_OUTOFMEMORY, MYF(0), (int) sizeof(select_send));
DBUG_RETURN(1);
}
if (send_prep_stmt(stmt, ha_table->fields.elements) ||
@@ -2399,6 +2386,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
}
break;
case SQLCOM_CREATE_TABLE:
+ case SQLCOM_CREATE_SEQUENCE:
res= mysql_test_create_table(stmt);
break;
case SQLCOM_SHOW_CREATE:
@@ -2462,7 +2450,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
}
break;
case SQLCOM_CREATE_VIEW:
- if (lex->create_view_mode == VIEW_ALTER)
+ if (lex->create_view->mode == VIEW_ALTER)
{
my_message(ER_UNSUPPORTED_PS, ER_THD(thd, ER_UNSUPPORTED_PS), MYF(0));
goto error;
@@ -2500,8 +2488,10 @@ static bool check_prepared_statement(Prepared_statement *stmt)
*/
case SQLCOM_SHOW_EXPLAIN:
case SQLCOM_DROP_TABLE:
+ case SQLCOM_DROP_SEQUENCE:
case SQLCOM_RENAME_TABLE:
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_ALTER_SEQUENCE:
case SQLCOM_COMMIT:
case SQLCOM_CREATE_INDEX:
case SQLCOM_DROP_INDEX:
@@ -2783,7 +2773,7 @@ bool LEX::get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer)
void mysql_sql_stmt_prepare(THD *thd)
{
LEX *lex= thd->lex;
- LEX_STRING *name= &lex->prepared_stmt_name;
+ LEX_CSTRING *name= &lex->prepared_stmt_name;
Prepared_statement *stmt;
LEX_CSTRING query;
DBUG_ENTER("mysql_sql_stmt_prepare");
@@ -3217,7 +3207,7 @@ void mysql_sql_stmt_execute(THD *thd)
{
LEX *lex= thd->lex;
Prepared_statement *stmt;
- LEX_STRING *name= &lex->prepared_stmt_name;
+ LEX_CSTRING *name= &lex->prepared_stmt_name;
/* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
DBUG_ENTER("mysql_sql_stmt_execute");
@@ -3438,7 +3428,7 @@ void mysqld_stmt_close(THD *thd, char *packet)
void mysql_sql_stmt_close(THD *thd)
{
Prepared_statement* stmt;
- LEX_STRING *name= &thd->lex->prepared_stmt_name;
+ LEX_CSTRING *name= &thd->lex->prepared_stmt_name;
DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", (int) name->length,
name->str));
@@ -3801,7 +3791,7 @@ void Prepared_statement::cleanup_stmt()
}
-bool Prepared_statement::set_name(LEX_STRING *name_arg)
+bool Prepared_statement::set_name(LEX_CSTRING *name_arg)
{
name.length= name_arg->length;
name.str= (char*) memdup_root(mem_root, name_arg->str, name_arg->length);
@@ -4459,7 +4449,7 @@ Prepared_statement::reprepare()
char saved_cur_db_name_buf[SAFE_NAME_LEN+1];
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
- LEX_STRING stmt_db_name= { db, db_length };
+ LEX_CSTRING stmt_db_name= { db, db_length };
bool cur_db_changed;
bool error;
@@ -4482,7 +4472,7 @@ Prepared_statement::reprepare()
thd->variables.sql_mode= save_sql_mode;
if (cur_db_changed)
- mysql_change_db(thd, &saved_cur_db_name, TRUE);
+ mysql_change_db(thd, (LEX_CSTRING*) &saved_cur_db_name, TRUE);
if (! error)
{
@@ -4580,7 +4570,7 @@ Prepared_statement::swap_prepared_statement(Prepared_statement *copy)
/* Don't swap flags: the copy has IS_SQL_PREPARE always set. */
/* swap_variables(uint, flags, copy->flags); */
/* Swap names, the old name is allocated in the wrong memory root */
- swap_variables(LEX_STRING, name, copy->name);
+ swap_variables(LEX_CSTRING, name, copy->name);
/* Ditto */
swap_variables(char *, db, copy->db);
swap_variables(size_t, db_length, copy->db_length);
@@ -4625,7 +4615,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed;
- LEX_STRING stmt_db_name= { db, db_length };
+ LEX_CSTRING stmt_db_name= { db, db_length };
status_var_increment(thd->status_var.com_stmt_execute);
@@ -4753,7 +4743,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
*/
if (cur_db_changed)
- mysql_change_db(thd, &saved_cur_db_name, TRUE);
+ mysql_change_db(thd, (LEX_CSTRING*) &saved_cur_db_name, TRUE);
/* Assert that if an error, no cursor is open */
DBUG_ASSERT(! (error && cursor));
@@ -4828,8 +4818,8 @@ bool Prepared_statement::execute_immediate(const char *query, uint query_len)
{
DBUG_ENTER("Prepared_statement::execute_immediate");
String expanded_query;
- static LEX_STRING execute_immediate_stmt_name=
- {(char*) STRING_WITH_LEN("(immediate)") };
+ static LEX_CSTRING execute_immediate_stmt_name=
+ {STRING_WITH_LEN("(immediate)") };
set_sql_prepare();
name= execute_immediate_stmt_name; // for DBUG_PRINT etc
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index f3b62991c5c..7206162792a 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -120,8 +120,10 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table)
continue;
field_info= &schema_table->fields_info[i];
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name) };
Item_field *field= new (thd->mem_root) Item_field(thd, context,
- NullS, NullS, field_info->field_name);
+ NullS, NullS, &field_name);
if (field)
{
field->set_name(thd, field_info->old_name,
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index 73b996e738e..c01ad90f5d2 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -166,7 +166,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
if (options & REFRESH_RELAY_LOG)
{
#ifdef HAVE_REPLICATION
- LEX_STRING connection_name;
+ LEX_CSTRING connection_name;
Master_info *mi;
if (thd)
connection_name= thd->lex->relay_log_connection_name;
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 1588644f0e1..2cba634e17c 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -33,8 +33,8 @@
static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
bool skip_error);
-static bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
- char *new_table_name, char *new_table_alias,
+static bool do_rename(THD *thd, TABLE_LIST *ren_table, const char *new_db,
+ const char *new_table_name, const char *new_table_alias,
bool skip_error);
static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
@@ -50,7 +50,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent)
bool binlog_error= 0;
TABLE_LIST *ren_table= 0;
int to_table;
- char *rename_log_table[2]= {NULL, NULL};
+ const char *rename_log_table[2]= {NULL, NULL};
DBUG_ENTER("mysql_rename_tables");
/*
@@ -254,8 +254,9 @@ do_rename_temporary(THD *thd, TABLE_LIST *ren_table, TABLE_LIST *new_table,
*/
static bool
-do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
- char *new_table_alias, bool skip_error)
+do_rename(THD *thd, TABLE_LIST *ren_table, const char *new_db,
+ const char *new_table_name, const char *new_table_alias,
+ bool skip_error)
{
int rc= 1;
handlerton *hton;
@@ -291,11 +292,11 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
if (!(rc= mysql_rename_table(hton, ren_table->db, old_alias,
new_db, new_alias, 0)))
{
- LEX_STRING db_name= { ren_table->db, ren_table->db_length };
- LEX_STRING table_name= { ren_table->table_name,
+ LEX_CSTRING db_name= { ren_table->db, ren_table->db_length };
+ LEX_CSTRING table_name= { ren_table->table_name,
ren_table->table_name_length };
- LEX_STRING new_table= { (char *) new_alias, strlen(new_alias) };
- LEX_STRING new_db_name= { (char*)new_db, strlen(new_db)};
+ LEX_CSTRING new_table= { new_alias, strlen(new_alias) };
+ LEX_CSTRING new_db_name= { new_db, strlen(new_db)};
(void) rename_table_in_stat_tables(thd, &db_name, &table_name,
&new_db_name, &new_table);
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index e312e9f35e4..c5fd142f620 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -865,7 +865,6 @@ get_binlog_list(MEM_ROOT *memroot)
!(e->name= strmake_root(memroot, fname, length)))
{
mysql_bin_log.unlock_index();
- my_error(ER_OUTOFMEMORY, MYF(0), length + 1 + sizeof(*e));
DBUG_RETURN(NULL);
}
e->next= current_list;
@@ -3045,7 +3044,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
{
/* connection was deleted while we waited for lock_slave_threads */
mi->unlock_slave_threads();
- my_error(WARN_NO_MASTER_INFO, mi->connection_name.length,
+ my_error(WARN_NO_MASTER_INFO, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(-1);
}
@@ -3303,7 +3302,7 @@ int reset_slave(THD *thd, Master_info* mi)
{
/* connection was deleted while we waited for lock_slave_threads */
mi->unlock_slave_threads();
- my_error(WARN_NO_MASTER_INFO, mi->connection_name.length,
+ my_error(WARN_NO_MASTER_INFO, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(-1);
}
@@ -3445,7 +3444,7 @@ static bool get_string_parameter(char *to, const char *from, size_t length,
uint from_numchars= cs->cset->numchars(cs, from, from + from_length);
if (from_numchars > length / cs->mbmaxlen)
{
- my_error(ER_WRONG_STRING_LENGTH, MYF(0), from, name, length / cs->mbmaxlen);
+ my_error(ER_WRONG_STRING_LENGTH, MYF(0), from, name, (int) (length / cs->mbmaxlen));
return 1;
}
memcpy(to, from, from_length+1);
@@ -3514,7 +3513,7 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
{
/* connection was deleted while we waited for lock_slave_threads */
mi->unlock_slave_threads();
- my_error(WARN_NO_MASTER_INFO, mi->connection_name.length,
+ my_error(WARN_NO_MASTER_INFO, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e8e399868db..29ca0491eba 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -321,8 +321,8 @@ void dbug_serve_apcs(THD *thd, int n_calls)
bool dbug_user_var_equals_int(THD *thd, const char *name, int value)
{
user_var_entry *var;
- LEX_STRING varname= {(char*)name, strlen(name)};
- if ((var= get_variable(&thd->user_vars, varname, FALSE)))
+ LEX_CSTRING varname= { name, strlen(name)};
+ if ((var= get_variable(&thd->user_vars, &varname, FALSE)))
{
bool null_value;
longlong var_value= var->val_int(&null_value);
@@ -346,7 +346,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
DBUG_ENTER("handle_select");
MYSQL_SELECT_START(thd->query());
- if (select_lex->master_unit()->is_union() ||
+ if (select_lex->master_unit()->is_unit_op() ||
select_lex->master_unit()->fake_select_lex)
res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
else
@@ -377,7 +377,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
res|= thd->is_error();
if (unlikely(res))
result->abort_result_set();
- if (thd->killed == ABORT_QUERY)
+ if (thd->killed == ABORT_QUERY && !thd->no_errors)
{
/*
If LIMIT ROWS EXAMINED interrupted query execution, issue a warning,
@@ -514,9 +514,9 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
new_ref= direct_ref ?
new (thd->mem_root) Item_direct_ref(thd, ref->context, item_ref, ref->table_name,
- ref->field_name, ref->alias_name_used) :
+ &ref->field_name, ref->alias_name_used) :
new (thd->mem_root) Item_ref(thd, ref->context, item_ref, ref->table_name,
- ref->field_name, ref->alias_name_used);
+ &ref->field_name, ref->alias_name_used);
if (!new_ref)
return TRUE;
ref->outer_ref= new_ref;
@@ -705,7 +705,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
select_lex= select_lex_arg;
select_lex->join= this;
join_list= &select_lex->top_join_list;
- union_part= unit_arg->is_union();
+ union_part= unit_arg->is_unit_op();
if (select_lex->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
@@ -1555,7 +1555,14 @@ JOIN::optimize_inner()
}
if (const_tables && !thd->locked_tables_mode &&
!(select_options & SELECT_NO_UNLOCK))
- mysql_unlock_some_tables(thd, table, const_tables);
+ {
+ /*
+ Unlock all tables, except sequences, as accessing these may still
+ require table updates
+ */
+ mysql_unlock_some_tables(thd, table, const_tables,
+ GET_LOCK_SKIP_SEQUENCES);
+ }
if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
@@ -5033,7 +5040,7 @@ Item_func_trig_cond::add_key_fields(JOIN *join, KEY_FIELD **key_fields,
if (!join->group_list && !join->order &&
join->unit->item &&
join->unit->item->substype() == Item_subselect::IN_SUBS &&
- !join->unit->is_union())
+ !join->unit->is_unit_op())
{
KEY_FIELD *save= *key_fields;
args[0]->add_key_fields(join, key_fields, and_level, usable_tables,
@@ -12909,10 +12916,15 @@ static bool check_simple_equality(THD *thd, const Item::Context &ctx,
else
{
/* None of the fields was found in multiple equalities */
- Item_equal *item_equal= new (thd->mem_root) Item_equal(thd,
- orig_left_item,
- orig_right_item,
- FALSE);
+ Type_handler_hybrid_field_type
+ tmp(orig_left_item->type_handler_for_comparison());
+ if (tmp.aggregate_for_comparison(orig_right_item->
+ type_handler_for_comparison()))
+ return false;
+ Item_equal *item_equal=
+ new (thd->mem_root) Item_equal(thd, tmp.type_handler(),
+ orig_left_item, orig_right_item,
+ false);
item_equal->set_context_field((Item_field*)left_item);
cond_equal->current_level.push_back(item_equal, thd->mem_root);
}
@@ -12997,8 +13009,14 @@ static bool check_simple_equality(THD *thd, const Item::Context &ctx,
}
else
{
- item_equal= new (thd->mem_root) Item_equal(thd, const_item2,
- orig_field_item, TRUE);
+ Type_handler_hybrid_field_type
+ tmp(orig_left_item->type_handler_for_comparison());
+ if (tmp.aggregate_for_comparison(orig_right_item->
+ type_handler_for_comparison()))
+ return false;
+ item_equal= new (thd->mem_root) Item_equal(thd, tmp.type_handler(),
+ const_item2,
+ orig_field_item, true);
item_equal->set_context_field(field_item);
cond_equal->current_level.push_back(item_equal, thd->mem_root);
}
@@ -13048,6 +13066,14 @@ static bool check_row_equality(THD *thd, const Arg_comparator *comparators,
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
{
+ /*
+ Item_splocal for ROW SP variables return Item::ROW_ITEM.
+ Here we know that left_item and right_item are not Item_splocal,
+ because ROW SP variables with nested ROWs are not supported yet.
+ It's safe to cast left_item and right_item to Item_row.
+ */
+ DBUG_ASSERT(!left_item->get_item_splocal());
+ DBUG_ASSERT(!right_item->get_item_splocal());
is_converted= check_row_equality(thd,
comparators[i].subcomparators(),
(Item_row *) left_item,
@@ -13059,7 +13085,7 @@ static bool check_row_equality(THD *thd, const Arg_comparator *comparators,
const Arg_comparator *tmp= &comparators[i];
is_converted= check_simple_equality(thd,
Item::Context(Item::ANY_SUBST,
- tmp->compare_type(),
+ tmp->compare_type_handler(),
tmp->compare_collation()),
left_item, right_item,
cond_equal);
@@ -13118,6 +13144,15 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal,
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
{
+ /*
+ Item_splocal::type() for ROW variables returns Item::ROW_ITEM.
+ Distinguish ROW-type Item_splocal from Item_row.
+ Example query:
+ SELECT 1 FROM DUAL WHERE row_sp_variable=ROW(100,200);
+ */
+ if (left_item->get_item_splocal() ||
+ right_item->get_item_splocal())
+ return false;
return check_row_equality(thd,
cmp.subcomparators(),
(Item_row *) left_item,
@@ -13126,7 +13161,7 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal,
}
return check_simple_equality(thd,
Context(ANY_SUBST,
- compare_type(),
+ compare_type_handler(),
compare_collation()),
left_item, right_item, cond_equal);
}
@@ -14197,71 +14232,11 @@ can_change_cond_ref_to_const(Item_bool_func2 *target,
Item_bool_func2 *source,
Item *source_expr, Item *source_const)
{
- if (!target_expr->eq(source_expr,0) ||
- target_value == source_const ||
- target->compare_type() != source->compare_type())
- return false;
- if (target->compare_type() == STRING_RESULT)
- {
- /*
- In this example:
- SET NAMES utf8 COLLATE utf8_german2_ci;
- DROP TABLE IF EXISTS t1;
- CREATE TABLE t1 (a CHAR(10) CHARACTER SET utf8);
- INSERT INTO t1 VALUES ('o-umlaut'),('oe');
- SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci AND a='oe';
-
- the query should return only the row with 'oe'.
- It should not return 'o-umlaut', because 'o-umlaut' does not match
- the right part of the condition: a='oe'
- ('o-umlaut' is not equal to 'oe' in utf8_general_ci,
- which is the collation of the field "a").
-
- If we change the right part from:
- ... AND a='oe'
- to
- ... AND 'oe' COLLATE utf8_german2_ci='oe'
- it will be evalulated to TRUE and removed from the condition,
- so the overall query will be simplified to:
-
- SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci;
-
- which will erroneously start to return both 'oe' and 'o-umlaut'.
- So changing "expr" to "const" is not possible if the effective
- collations of "target" and "source" are not exactly the same.
-
- Note, the code before the fix for MDEV-7152 only checked that
- collations of "source_const" and "target_value" are the same.
- This was not enough, as the bug report demonstrated.
- */
- return
- target->compare_collation() == source->compare_collation() &&
- target_value->collation.collation == source_const->collation.collation;
- }
- if (target->compare_type() == TIME_RESULT)
- {
- if (target_value->cmp_type() != TIME_RESULT)
- {
- /*
- Can't rewrite:
- WHERE COALESCE(time_column)='00:00:00'
- AND COALESCE(time_column)=DATE'2015-09-11'
- to
- WHERE DATE'2015-09-11'='00:00:00'
- AND COALESCE(time_column)=DATE'2015-09-11'
- because the left part will erroneously try to parse '00:00:00'
- as DATE, not as TIME.
-
- TODO: It could still be rewritten to:
- WHERE DATE'2015-09-11'=TIME'00:00:00'
- AND COALESCE(time_column)=DATE'2015-09-11'
- i.e. we need to replace both target_expr and target_value
- at the same time. This is not supported yet.
- */
- return false;
- }
- }
- return true; // Non-string comparison
+ return target_expr->eq(source_expr,0) &&
+ target_value != source_const &&
+ target->compare_type_handler()->
+ can_change_cond_ref_to_const(target, target_expr, target_value,
+ source, source_expr, source_const);
}
@@ -15949,7 +15924,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field,
*/
Field *create_tmp_field_from_field(THD *thd, Field *org_field,
- const char *name, TABLE *table,
+ LEX_CSTRING *name, TABLE *table,
Item_field *item)
{
Field *new_field;
@@ -15963,7 +15938,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
if (item)
item->result_field= new_field;
else
- new_field->field_name= name;
+ new_field->field_name= *name;
new_field->flags|= (org_field->flags & NO_DEFAULT_VALUE_FLAG);
if (org_field->maybe_null() || (item && item->maybe_null))
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
@@ -15982,45 +15957,33 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
}
-Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
+Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
+{
+ const Type_handler *h= &type_handler_long;
+ if (max_char_length() > convert_int_length)
+ h= &type_handler_longlong;
+ return h->make_and_init_table_field(&name, Record_addr(maybe_null),
+ *this, table);
+}
+
+
+Field *Item_sum::create_tmp_field(bool group, TABLE *table)
{
Field *UNINIT_VAR(new_field);
MEM_ROOT *mem_root= table->in_use->mem_root;
switch (cmp_type()) {
case REAL_RESULT:
+ {
new_field= new (mem_root)
- Field_double(max_length, maybe_null, name, decimals, TRUE);
+ Field_double(max_char_length(), maybe_null, &name, decimals, TRUE);
break;
+ }
case INT_RESULT:
- /*
- Select an integer type with the minimal fit precision.
- convert_int_length is sign inclusive, don't consider the sign.
- */
- if (max_char_length() > convert_int_length)
- new_field= new (mem_root)
- Field_longlong(max_char_length(), maybe_null, name, unsigned_flag);
- else
- new_field= new (mem_root)
- Field_long(max_char_length(), maybe_null, name, unsigned_flag);
- break;
case TIME_RESULT:
- new_field= tmp_table_field_from_field_type(table, true, false);
- break;
- case STRING_RESULT:
- DBUG_ASSERT(collation.collation);
- /*
- GEOMETRY fields have STRING_RESULT result type.
- To preserve type they needed to be handled separately.
- */
- if (field_type() == MYSQL_TYPE_GEOMETRY)
- new_field= tmp_table_field_from_field_type(table, true, false);
- else
- new_field= make_string_field(table);
- new_field->set_derivation(collation.derivation, collation.repertoire);
- break;
case DECIMAL_RESULT:
- new_field= Field_new_decimal::create_from_item(mem_root, this);
+ case STRING_RESULT:
+ new_field= tmp_table_field_from_field_type(table);
break;
case ROW_RESULT:
// This case should never be choosen
@@ -16034,6 +15997,22 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
}
+static void create_tmp_field_from_item_finalize(THD *thd,
+ Field *new_field,
+ Item *item,
+ Item ***copy_func,
+ bool modify_item)
+{
+ if (copy_func &&
+ (item->is_result_field() ||
+ (item->real_item()->is_result_field())))
+ *((*copy_func)++) = item; // Save for copy_funcs
+ if (modify_item)
+ item->set_result_field(new_field);
+ if (item->type() == Item::NULL_ITEM)
+ new_field->is_created_from_null_item= TRUE;
+}
+
/**
Create field for temporary table using type of given item.
@@ -16064,16 +16043,9 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
{
Field *UNINIT_VAR(new_field);
DBUG_ASSERT(thd == table->in_use);
- new_field= item->Item::create_tmp_field(false, table);
-
- if (copy_func &&
- (item->is_result_field() ||
- (item->real_item()->is_result_field())))
- *((*copy_func)++) = item; // Save for copy_funcs
- if (modify_item)
- item->set_result_field(new_field);
- if (item->type() == Item::NULL_ITEM)
- new_field->is_created_from_null_item= TRUE;
+ if ((new_field= item->create_tmp_field(false, table)))
+ create_tmp_field_from_item_finalize(thd, new_field, item,
+ copy_func, modify_item);
return new_field;
}
@@ -16097,15 +16069,16 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
{
Field *field;
if (max_length > MAX_FIELD_VARCHARLENGTH)
- field= new Field_blob(max_length, maybe_null, name, collation.collation);
+ field= new Field_blob(max_length, maybe_null, &name,
+ collation.collation);
else
- field= new Field_varstring(max_length, maybe_null, name,
+ field= new Field_varstring(max_length, maybe_null, &name,
table->s, collation.collation);
if (field)
field->init(table);
return field;
}
- return tmp_table_field_from_field_type(table, false, false);
+ return tmp_table_field_from_field_type(table);
}
@@ -16147,6 +16120,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item::Type orig_type= type;
Item *orig_item= 0;
+ DBUG_ASSERT(thd == table->in_use);
+
if (type != Item::FIELD_ITEM &&
item->real_item()->type() == Item::FIELD_ITEM)
{
@@ -16156,6 +16131,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
}
switch (type) {
+ case Item::TYPE_HOLDER:
case Item::SUM_FUNC_ITEM:
{
result= item->create_tmp_field(group, table);
@@ -16204,19 +16180,25 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else if (table_cant_handle_bit_fields && field->field->type() ==
MYSQL_TYPE_BIT)
{
+ const Type_handler *handler= item->type_handler_long_or_longlong();
*from_field= field->field;
- result= create_tmp_field_from_item(thd, item, table, copy_func,
- modify_item);
+ if ((result=
+ handler->make_and_init_table_field(&item->name,
+ Record_addr(item->maybe_null),
+ *item, table)))
+ create_tmp_field_from_item_finalize(thd, result, item,
+ copy_func, modify_item);
if (result && modify_item)
field->result_field= result;
}
else
+ {
+ LEX_CSTRING *tmp= orig_item ? &orig_item->name : &item->name;
result= create_tmp_field_from_field(thd, (*from_field= field->field),
- orig_item ? orig_item->name :
- item->name,
- table,
+ tmp, table,
modify_item ? field :
NULL);
+ }
if (orig_type == Item::REF_ITEM && orig_modify)
((Item_ref*)orig_item)->set_result_field(result);
/*
@@ -16244,11 +16226,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
{
*((*copy_func)++)= item;
}
-
Field *result_field=
create_tmp_field_from_field(thd,
sp_result_field,
- item_func_sp->name,
+ &item_func_sp->name,
table,
NULL);
@@ -16285,11 +16266,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
return create_tmp_field_from_item(thd, item, table,
(make_copy_field ? 0 : copy_func),
modify_item);
- case Item::TYPE_HOLDER:
- result= ((Item_type_holder *)item)->make_field_by_type(table);
- result->set_derivation(item->collation.derivation,
- item->collation.repertoire);
- return result;
default: // Dosen't have to be stored
return 0;
}
@@ -16600,6 +16576,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
distinct, false);
if (!new_field)
goto err; // Should be OOM
+ DBUG_ASSERT(!new_field->field_name.str || strlen(new_field->field_name.str) == new_field->field_name.length);
tmp_from_field++;
reclength+=new_field->pack_length();
if (new_field->flags & BLOB_FLAG)
@@ -16675,6 +16652,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
goto err; // Got OOM
continue; // Some kind of const item
}
+ DBUG_ASSERT(!new_field->field_name.str || strlen(new_field->field_name.str) == new_field->field_name.length);
if (type == Item::SUM_FUNC_ITEM)
{
Item_sum *agg_item= (Item_sum *) item;
@@ -17118,7 +17096,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
(uchar*) 0,
(uint) 0,
Field::NONE,
- NullS, &my_charset_bin);
+ &null_clex_str, &my_charset_bin);
if (!key_part_info->field)
goto err;
key_part_info->field->init(table);
@@ -17240,18 +17218,18 @@ bool Virtual_tmp_table::init(uint field_count)
};
-bool Virtual_tmp_table::add(List<Column_definition> &field_list)
+bool Virtual_tmp_table::add(List<Spvar_definition> &field_list)
{
/* Create all fields and calculate the total length of record */
- Column_definition *cdef; /* column definition */
- List_iterator_fast<Column_definition> it(field_list);
+ Spvar_definition *cdef; /* column definition */
+ List_iterator_fast<Spvar_definition> it(field_list);
for ( ; (cdef= it++); )
{
Field *tmp;
if (!(tmp= cdef->make_field(s, in_use->mem_root, 0,
(uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
f_maybe_null(cdef->pack_flag) ? 1 : 0,
- cdef->field_name)))
+ &cdef->field_name)))
return true;
add(tmp);
}
@@ -22229,7 +22207,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_NON_UNIQ_ERROR,
ER_THD(thd, ER_NON_UNIQ_ERROR),
- ((Item_ident*) order_item)->field_name,
+ ((Item_ident*) order_item)->field_name.str,
thd->where);
}
}
@@ -23269,14 +23247,15 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
ifield->db_name= iref->db_name;
}
#ifndef DBUG_OFF
- if (!item_field->name)
+ if (!item_field->name.str)
{
char buff[256];
String str(buff,sizeof(buff),&my_charset_bin);
str.length(0);
str.extra_allocation(1024);
item->print(&str, QT_ORDINARY);
- item_field->name= thd->strmake(str.ptr(),str.length());
+ item_field->name.str= thd->strmake(str.ptr(), str.length());
+ item_field->name.length= str.length();
}
#endif
}
@@ -23632,8 +23611,9 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
if (item->eq(*group_tmp->item,0))
{
Item *new_item;
- if (!(new_item= new (thd->mem_root) Item_ref(thd, context, group_tmp->item, 0,
- item->name)))
+ if (!(new_item= new (thd->mem_root) Item_ref(thd, context,
+ group_tmp->item, 0,
+ &item->name)))
return 1; // fatal_error is set
thd->change_item_tree(arg, new_item);
arg_changed= TRUE;
@@ -24669,6 +24649,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain->select_id= join->select_lex->select_number;
explain->select_type= join->select_lex->type;
+ explain->linkage= select_lex->linkage;
explain->using_temporary= need_tmp;
explain->using_filesort= need_order_arg;
/* Setting explain->message means that all other members are invalid */
@@ -24687,6 +24668,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
explain->select_id= select_lex->select_number;
explain->select_type= select_lex->type;
+ explain->linkage= select_lex->linkage;
explain->using_temporary= need_tmp;
explain->using_filesort= need_order_arg;
explain->message= "Storage engine handles GROUP BY";
@@ -24706,6 +24688,7 @@ int JOIN::save_explain_data_intern(Explain_query *output,
join->select_lex->set_explain_type(true);
xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type;
+ xpl_sel->linkage= select_lex->linkage;
if (select_lex->master_unit()->derived)
xpl_sel->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
@@ -24881,12 +24864,12 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
sl->options|= SELECT_DESCRIBE;
}
- if (unit->is_union())
+ if (unit->is_unit_op())
{
if (unit->union_needs_tmp_table() && unit->fake_select_lex)
{
unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // just for initialization
- unit->fake_select_lex->type= "UNION RESULT";
+ unit->fake_select_lex->type= unit_operation_text[unit->common_op()];
unit->fake_select_lex->options|= SELECT_DESCRIBE;
}
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
@@ -25265,6 +25248,17 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
{
DBUG_ASSERT(thd);
+ if ((query_type & QT_SHOW_SELECT_NUMBER) &&
+ thd->lex->all_selects_list &&
+ thd->lex->all_selects_list->link_next &&
+ select_number != UINT_MAX &&
+ select_number != INT_MAX)
+ {
+ str->append("/* select#");
+ str->append_ulonglong(select_number);
+ str->append(" */ ");
+ }
+
str->append(STRING_WITH_LEN("select "));
if (join && join->cleaned)
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 886a66c3ef4..7ee752dc84e 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1724,7 +1724,7 @@ void copy_fields(TMP_TABLE_PARAM *param);
bool copy_funcs(Item **func_ptr, const THD *thd);
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
Field* create_tmp_field_from_field(THD *thd, Field* org_field,
- const char *name, TABLE *table,
+ LEX_CSTRING *name, TABLE *table,
Item_field *item);
bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
@@ -2042,6 +2042,8 @@ public:
bzero(this, sizeof(*this));
temp_pool_slot= MY_BIT_NONE;
in_use= thd;
+ copy_blobs= true;
+ alias.set("", 0, &my_charset_bin);
}
~Virtual_tmp_table()
@@ -2085,11 +2087,11 @@ public:
}
/**
- Add fields from a Column_definition list
+ Add fields from a Spvar_definition list
@returns false - on success.
@returns true - on error.
*/
- bool add(List<Column_definition> &field_list);
+ bool add(List<Spvar_definition> &field_list);
/**
Open a virtual table for read/write:
@@ -2127,7 +2129,7 @@ public:
*/
inline TABLE *
-create_virtual_tmp_table(THD *thd, List<Column_definition> &field_list)
+create_virtual_tmp_table(THD *thd, List<Spvar_definition> &field_list)
{
Virtual_tmp_table *table;
if (!(table= new(thd) Virtual_tmp_table(thd)))
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
new file mode 100644
index 00000000000..be360c59e34
--- /dev/null
+++ b/sql/sql_sequence.cc
@@ -0,0 +1,931 @@
+/*
+ Copyright (c) 2017, MariaDB Corporation, Alibaba Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "sql_class.h"
+#include "sql_list.h"
+#include "sql_sequence.h"
+#include "ha_sequence.h"
+#include "sql_base.h"
+#include "sql_table.h" // write_bin_log
+#include "transaction.h"
+#include "lock.h"
+#include "sql_acl.h"
+
+struct Field_definition
+{
+ const char *field_name;
+ uint length;
+ const Type_handler *type_handler;
+ LEX_CSTRING comment;
+ ulong flags;
+};
+
+/*
+ Structure for all SEQUENCE tables
+
+ Note that the first field is named "next_val" to all us to have
+ NEXTVAL a reserved word that will on access be changed to
+ NEXTVAL(sequence_table). For this to work, the table can't have
+ a column named NEXTVAL.
+*/
+
+#define FL (NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG)
+
+static Field_definition sequence_structure[]=
+{
+ {"next_not_cached_value", 21, &type_handler_longlong,
+ {STRING_WITH_LEN("")}, FL},
+ {"minimum_value", 21, &type_handler_longlong, STRING_WITH_LEN(""), FL},
+ {"maximum_value", 21, &type_handler_longlong, STRING_WITH_LEN(""), FL},
+ {"start_value", 21, &type_handler_longlong, {STRING_WITH_LEN("start value when sequences is created or value if RESTART is used")}, FL},
+ {"increment", 21, &type_handler_longlong,
+ {C_STRING_WITH_LEN("increment value")}, FL},
+ {"cache_size", 21, &type_handler_longlong, STRING_WITH_LEN(""),
+ FL | UNSIGNED_FLAG},
+ {"cycle_option", 1, &type_handler_tiny, {STRING_WITH_LEN("0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed")},
+ FL | UNSIGNED_FLAG },
+ {"cycle_count", 21, &type_handler_longlong,
+ {STRING_WITH_LEN("How many cycles have been done")}, FL},
+ {NULL, 0, &type_handler_longlong, {STRING_WITH_LEN("")}, 0}
+};
+
+#undef FL
+
+
+#define MAX_AUTO_INCREMENT_VALUE 65535
+
+/*
+ Check whether sequence values are valid.
+ Sets default values for fields that are not used, according to Oracle spec.
+
+ RETURN VALUES
+ false valid
+ true invalid
+*/
+
+bool sequence_definition::check_and_adjust(bool set_reserved_until)
+{
+ longlong max_increment;
+ DBUG_ENTER("sequence_definition::check");
+
+ if (!(real_increment= increment))
+ real_increment= global_system_variables.auto_increment_increment;
+
+ /*
+ If min_value is not set, set it to LONGLONG_MIN or 1, depending on
+ increment
+ */
+ if (!(used_fields & seq_field_used_min_value))
+ min_value= real_increment < 0 ? LONGLONG_MIN+1 : 1;
+
+ /*
+ If min_value is not set, set it to LONGLONG_MAX or -1, depending on
+ real_increment
+ */
+ if (!(used_fields & seq_field_used_max_value))
+ max_value= real_increment < 0 ? -1 : LONGLONG_MAX-1;
+
+ if (!(used_fields & seq_field_used_start))
+ {
+ /* Use min_value or max_value for start depending on real_increment */
+ start= real_increment < 0 ? max_value : min_value;
+ }
+
+ if (set_reserved_until)
+ reserved_until= start;
+
+ adjust_values(reserved_until);
+
+ /* To ensure that cache * real_increment will never overflow */
+ max_increment= (real_increment ?
+ labs(real_increment) :
+ MAX_AUTO_INCREMENT_VALUE);
+
+ if (max_value >= start &&
+ max_value > min_value &&
+ start >= min_value &&
+ max_value != LONGLONG_MAX &&
+ min_value != LONGLONG_MIN &&
+ cache < (LONGLONG_MAX - max_increment) / max_increment &&
+ ((real_increment > 0 && reserved_until >= min_value) ||
+ (real_increment < 0 && reserved_until <= max_value)))
+ DBUG_RETURN(FALSE);
+
+ DBUG_RETURN(TRUE); // Error
+}
+
+
+/*
+ Read sequence values from a table
+*/
+
+void sequence_definition::read_fields(TABLE *table)
+{
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
+ reserved_until= table->field[0]->val_int();
+ min_value= table->field[1]->val_int();
+ max_value= table->field[2]->val_int();
+ start= table->field[3]->val_int();
+ increment= table->field[4]->val_int();
+ cache= table->field[5]->val_int();
+ cycle= table->field[6]->val_int();
+ round= table->field[7]->val_int();
+ dbug_tmp_restore_column_map(table->read_set, old_map);
+ used_fields= ~(uint) 0;
+ print_dbug();
+}
+
+
+/*
+ Store sequence into a table row
+*/
+
+void sequence_definition::store_fields(TABLE *table)
+{
+ my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
+
+ /* zero possible delete markers & null bits */
+ memcpy(table->record[0], table->s->default_values, table->s->null_bytes);
+ table->field[0]->store(reserved_until, 0);
+ table->field[1]->store(min_value, 0);
+ table->field[2]->store(max_value, 0);
+ table->field[3]->store(start, 0);
+ table->field[4]->store(increment, 0);
+ table->field[5]->store(cache, 0);
+ table->field[6]->store((longlong) cycle != 0, 0);
+ table->field[7]->store((longlong) round, 1);
+
+ dbug_tmp_restore_column_map(table->write_set, old_map);
+ print_dbug();
+}
+
+
+/*
+ Check the sequence fields through seq_fields when createing a sequence.
+
+ RETURN VALUES
+ false Success
+ true Failure
+*/
+
+bool check_sequence_fields(LEX *lex, List<Create_field> *fields)
+{
+ Create_field *field;
+ List_iterator_fast<Create_field> it(*fields);
+ uint field_count;
+ uint field_no;
+ const char *reason;
+ DBUG_ENTER("check_sequence_fields");
+
+ field_count= fields->elements;
+ if (field_count != array_elements(sequence_structure)-1)
+ {
+ reason= "Wrong number of columns";
+ goto err;
+ }
+ if (lex->alter_info.key_list.elements > 0)
+ {
+ reason= "Sequence tables cannot have any keys";
+ goto err;
+ }
+
+ for (field_no= 0; (field= it++); field_no++)
+ {
+ Field_definition *field_def= &sequence_structure[field_no];
+ if (my_strcasecmp(system_charset_info, field_def->field_name,
+ field->field_name.str) ||
+ field->flags != field_def->flags ||
+ field->type_handler() != field_def->type_handler)
+ {
+ reason= field->field_name.str;
+ goto err;
+ }
+ }
+ DBUG_RETURN(FALSE);
+
+err:
+ my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0),
+ lex->select_lex.table_list.first->db,
+ lex->select_lex.table_list.first->table_name, reason);
+ DBUG_RETURN(TRUE);
+}
+
+
+/*
+ Create the fields for a SEQUENCE TABLE
+
+ RETURN VALUES
+ false Success
+ true Failure (out of memory)
+*/
+
+bool prepare_sequence_fields(THD *thd, List<Create_field> *fields)
+{
+ Field_definition *field_info;
+ DBUG_ENTER("prepare_sequence_fields");
+
+ for (field_info= sequence_structure; field_info->field_name ; field_info++)
+ {
+ Create_field *new_field;
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name)};
+
+ if (unlikely(!(new_field= new Create_field())))
+ DBUG_RETURN(TRUE); /* purify inspected */
+
+ new_field->field_name= field_name;
+ new_field->set_handler(field_info->type_handler);
+ new_field->length= field_info->length;
+ new_field->char_length= field_info->length;
+ new_field->comment= field_info->comment;
+ new_field->flags= field_info->flags;
+ if (unlikely(fields->push_back(new_field)))
+ DBUG_RETURN(TRUE); /* purify inspected */
+ }
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ Initialize the sequence table record as part of CREATE SEQUENCE
+
+ Store one row with sequence information.
+
+ RETURN VALUES
+ false Success
+ true Failure. Error reported.
+
+ NOTES
+ This function is called as part of CREATE SEQUENCE. When called
+ there are now active transactions and no open tables.
+ There is also a MDL lock on the table.
+*/
+
+bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list)
+{
+ int error;
+ TABLE *table;
+ TABLE_LIST::enum_open_strategy save_open_strategy;
+ Reprepare_observer *save_reprepare_observer;
+ sequence_definition *seq= lex->create_info.seq_create_info;
+ bool temporary_table= table_list->table != 0;
+ DBUG_ENTER("sequence_insert");
+
+ /* If not temporary table */
+ if (!temporary_table)
+ {
+ /* Table was locked as part of create table. Free it but keep MDL locks */
+ close_thread_tables(thd);
+ table_list->lock_type= TL_WRITE_DEFAULT;
+ table_list->updating= 1;
+ /*
+ The FOR CREATE flag is needed to ensure that ha_open() doesn't try to
+ read the not yet existing row in the sequence table
+ */
+ thd->open_options|= HA_OPEN_FOR_CREATE;
+ save_open_strategy= table_list->open_strategy;
+ /*
+ We have to reset the reprepare observer to be able to open the
+ table under prepared statements.
+ */
+ save_reprepare_observer= thd->m_reprepare_observer;
+ thd->m_reprepare_observer= 0;
+ table_list->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
+ table_list->open_type= OT_BASE_ONLY;
+ error= open_and_lock_tables(thd, table_list, FALSE,
+ MYSQL_LOCK_IGNORE_TIMEOUT |
+ MYSQL_OPEN_HAS_MDL_LOCK);
+ table_list->open_strategy= save_open_strategy;
+ thd->open_options&= ~HA_OPEN_FOR_CREATE;
+ thd->m_reprepare_observer= save_reprepare_observer;
+ if (error)
+ DBUG_RETURN(TRUE); /* purify inspected */
+ }
+
+ table= table_list->table;
+
+ /*
+ seq is 0 if sequence was created with CREATE TABLE instead of
+ CREATE SEQUENCE
+ */
+ if (!seq)
+ {
+ if (!(seq= new (thd->mem_root) sequence_definition))
+ DBUG_RETURN(TRUE); // EOM
+ }
+
+ seq->reserved_until= seq->start;
+ error= seq->write_initial_sequence(table);
+
+ trans_commit_stmt(thd);
+ trans_commit_implicit(thd);
+ if (!temporary_table)
+ close_thread_tables(thd);
+ thd->mdl_context.release_transactional_locks();
+ DBUG_RETURN(error);
+}
+
+
+/* Create a SQUENCE object */
+
+SEQUENCE::SEQUENCE() :all_values_used(0), initialized(SEQ_UNINTIALIZED), table(0)
+{
+ mysql_rwlock_init(key_LOCK_SEQUENCE, &mutex);
+}
+
+SEQUENCE::~SEQUENCE()
+{
+ mysql_rwlock_destroy(&mutex);
+}
+
+/*
+ The following functions is to ensure that we when reserve new values
+ trough sequence object sequence we have only one writer at at time.
+ A sequence table can have many readers (trough normal SELECT's).
+
+ We mark that we have a write lock in the table object so that
+ ha_sequence::ha_write() can check if we have a lock. If already locked, then
+ ha_write() knows that we are running a sequence operation. If not, then
+ ha_write() knows that it's an INSERT.
+*/
+
+void SEQUENCE::write_lock(TABLE *table)
+{
+ DBUG_ASSERT(((ha_sequence*) table->file)->is_locked() == 0);
+ mysql_rwlock_wrlock(&mutex);
+ ((ha_sequence*) table->file)->write_lock();
+}
+void SEQUENCE::write_unlock(TABLE *table)
+{
+ ((ha_sequence*) table->file)->unlock();
+ mysql_rwlock_unlock(&mutex);
+}
+void SEQUENCE::read_lock(TABLE *table)
+{
+ if (!((ha_sequence*) table->file)->is_locked())
+ mysql_rwlock_rdlock(&mutex);
+}
+void SEQUENCE::read_unlock(TABLE *table)
+{
+ if (!((ha_sequence*) table->file)->is_locked())
+ mysql_rwlock_unlock(&mutex);
+}
+
+/**
+ Read values from the sequence tables to table_share->sequence.
+ This is called from ha_open() when the table is not yet locked
+*/
+
+int SEQUENCE::read_initial_values(TABLE *table_arg)
+{
+ int error= 0;
+ enum thr_lock_type save_lock_type;
+ MDL_request mdl_request; // Empty constructor!
+ DBUG_ENTER("SEQUENCE::read_initial_values");
+
+ if (likely(initialized != SEQ_UNINTIALIZED))
+ DBUG_RETURN(0);
+ table= table_arg;
+ write_lock(table);
+ if (likely(initialized == SEQ_UNINTIALIZED))
+ {
+ MYSQL_LOCK *lock;
+ bool mdl_lock_used= 0;
+ THD *thd= table->in_use;
+ bool has_active_transaction= !thd->transaction.stmt.is_empty();
+ /*
+ There is already a mdl_ticket for this table. However, for list_fields
+ the MDL lock is of type MDL_SHARED_HIGH_PRIO which is not usable
+ for doing a able lock. Get a proper read lock to solve this.
+ */
+ if (table->mdl_ticket == 0)
+ {
+ MDL_request_list mdl_requests;
+ mdl_lock_used= 1;
+ /*
+ This happens if first request is SHOW CREATE TABLE or LIST FIELDS
+ where we don't have a mdl lock on the table
+ */
+
+ mdl_request.init(MDL_key::TABLE,
+ table->s->db.str,
+ table->s->table_name.str,
+ MDL_SHARED_READ, MDL_EXPLICIT);
+ mdl_requests.push_front(&mdl_request);
+ if (thd->mdl_context.acquire_locks(&mdl_requests,
+ thd->variables.lock_wait_timeout))
+ DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT);
+ }
+ save_lock_type= table->reginfo.lock_type;
+ table->reginfo.lock_type= TL_READ;
+ if (!(lock= mysql_lock_tables(thd, &table, 1,
+ MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY)))
+ {
+ if (mdl_lock_used)
+ thd->mdl_context.release_lock(mdl_request.ticket);
+ DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT);
+ }
+ if (!(error= read_stored_values()))
+ initialized= SEQ_READY_TO_USE;
+ mysql_unlock_tables(thd, lock, 0);
+ if (mdl_lock_used)
+ thd->mdl_context.release_lock(mdl_request.ticket);
+
+ /* Reset value to default */
+ table->reginfo.lock_type= save_lock_type;
+ /*
+ Doing mysql_lock_tables() may have started a read only transaction.
+ If that happend, it's better that we commit it now, as a lot of
+ code assumes that there is no active stmt transaction directly after
+ open_tables()
+ */
+ if (!has_active_transaction && !thd->transaction.stmt.is_empty())
+ trans_commit_stmt(thd);
+ }
+ write_unlock(table);
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Do the actiual reading of data from sequence table and
+ update values in the sequence object.
+
+ Called once from when table is opened
+*/
+
+int SEQUENCE::read_stored_values()
+{
+ int error;
+ my_bitmap_map *save_read_set;
+ DBUG_ENTER("SEQUENCE::read_stored_values");
+
+ save_read_set= tmp_use_all_columns(table, table->read_set);
+ error= table->file->ha_read_first_row(table->record[0], MAX_KEY);
+ tmp_restore_column_map(table->read_set, save_read_set);
+
+ if (error)
+ {
+ table->file->print_error(error, MYF(0));
+ DBUG_RETURN(error);
+ }
+ read_fields(table);
+ adjust_values(reserved_until);
+
+ all_values_used= 0;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Adjust values after reading a the stored state
+*/
+
+void sequence_definition::adjust_values(longlong next_value)
+{
+ next_free_value= next_value;
+ if (!(real_increment= increment))
+ {
+ longlong offset= 0;
+ longlong off, to_add;
+ /* Use auto_increment_increment and auto_increment_offset */
+
+ if ((real_increment= global_system_variables.auto_increment_increment)
+ != 1)
+ offset= global_system_variables.auto_increment_offset;
+
+ /*
+ Ensure that next_free_value has the right offset, so that we
+ can generate a serie by just adding real_increment.
+ */
+ off= next_free_value % real_increment;
+ if (off < 0)
+ off+= real_increment;
+ to_add= (real_increment + offset - off) % real_increment;
+
+ /*
+ Check if add will make next_free_value bigger than max_value,
+ taken into account that next_free_value or max_value addition
+ may overflow
+ */
+ if (next_free_value > max_value - to_add ||
+ next_free_value + to_add > max_value)
+ next_free_value= max_value+1;
+ else
+ {
+ next_free_value+= to_add;
+ DBUG_ASSERT(next_free_value % real_increment == offset &&
+ next_free_value >= reserved_until);
+ }
+ }
+}
+
+
+/**
+ Write initial sequence information for CREATE and ALTER to sequence table
+*/
+
+int sequence_definition::write_initial_sequence(TABLE *table)
+{
+ int error;
+ THD *thd= table->in_use;
+ MY_BITMAP *save_write_set;
+
+ store_fields(table);
+ /* Store the sequence values in table share */
+ table->s->sequence->copy(this);
+ /*
+ Sequence values will be replicated as a statement
+ like 'create sequence'. So disable binary log temporarily
+ */
+ tmp_disable_binlog(thd);
+ save_write_set= table->write_set;
+ table->write_set= &table->s->all_set;
+ table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
+ error= table->file->ha_write_row(table->record[0]);
+ table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
+ reenable_binlog(thd);
+ table->write_set= save_write_set;
+ if (error)
+ table->file->print_error(error, MYF(0));
+ else
+ {
+ /*
+ Sequence structure is up to date and table has one row,
+ sequence is now usable
+ */
+ table->s->sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
+ }
+ return error;
+}
+
+
+/**
+ Store current sequence values into the sequence table
+*/
+
+int sequence_definition::write(TABLE *table, bool all_fields)
+{
+ int error;
+ MY_BITMAP *save_rpl_write_set, *save_write_set, *save_read_set;
+ DBUG_ASSERT(((ha_sequence*) table->file)->is_locked());
+
+ save_rpl_write_set= table->rpl_write_set;
+ if (likely(!all_fields))
+ {
+ /* Only write next_value and round to binary log */
+ table->rpl_write_set= &table->def_rpl_write_set;
+ bitmap_clear_all(table->rpl_write_set);
+ bitmap_set_bit(table->rpl_write_set, NEXT_FIELD_NO);
+ bitmap_set_bit(table->rpl_write_set, ROUND_FIELD_NO);
+ }
+ else
+ table->rpl_write_set= &table->s->all_set;
+
+ /* Update table */
+ save_write_set= table->write_set;
+ save_read_set= table->read_set;
+ table->read_set= table->write_set= &table->s->all_set;
+ table->file->column_bitmaps_signal();
+ store_fields(table);
+ if ((error= table->file->ha_write_row(table->record[0])))
+ table->file->print_error(error, MYF(0));
+ table->rpl_write_set= save_rpl_write_set;
+ table->read_set= save_read_set;
+ table->write_set= save_write_set;
+ table->file->column_bitmaps_signal();
+ return error;
+}
+
+
+/**
+ Get next value for sequence
+
+ @param in table Sequence table
+ @param in second_round
+ 1 if recursive call (out of values once)
+ @param out error Set this to <> 0 in case of error
+ push_warning_printf(WARN_LEVEL_WARN) has been called
+
+
+  @retval 0 Next number or error. Check error variable
+ # Next sequence number
+
+ NOTES:
+ Return next_free_value and increment next_free_value to next allowed
+ value or reserved_value if out of range
+ if next_free_value >= reserved_value reserve a new range by writing
+ a record to the sequence table.
+
+ The state of the variables:
+ next_free_value contains next value to use. It may be
+ bigger than max_value or less than min_value if end of sequence.
+ reserved_until contains the last value written to the file. All
+ values up to this one can be used.
+ If next_free_value >= reserved_until we have to reserve new
+ values from the sequence.
+*/
+
+longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
+{
+ longlong res_value, org_reserved_until, add_to;
+ bool out_of_values;
+ DBUG_ENTER("SEQUENCE::next_value");
+
+ *error= 0;
+ if (!second_round)
+ write_lock(table);
+
+ res_value= next_free_value;
+ next_free_value= increment_value(next_free_value);
+
+ if ((real_increment > 0 && res_value < reserved_until) ||
+ (real_increment < 0 && res_value > reserved_until))
+ {
+ write_unlock(table);
+ DBUG_RETURN(res_value);
+ }
+
+ if (all_values_used)
+ goto err;
+
+ org_reserved_until= reserved_until;
+
+ /*
+ Out of cached values, reserve 'cache' new ones
+ The cache value is checked on insert so the following can't
+ overflow
+ */
+ add_to= cache ? real_increment * cache : real_increment;
+ out_of_values= 0;
+
+ if (real_increment > 0)
+ {
+ if (reserved_until + add_to > max_value ||
+ reserved_until > max_value - add_to)
+ {
+ reserved_until= max_value + 1;
+ out_of_values= res_value >= reserved_until;
+ }
+ else
+ reserved_until+= add_to;
+ }
+ else
+ {
+ if (reserved_until + add_to < min_value ||
+ reserved_until < min_value - add_to)
+ {
+ reserved_until= min_value - 1;
+ out_of_values= res_value <= reserved_until;
+ }
+ else
+ reserved_until+= add_to;
+ }
+ if (out_of_values)
+ {
+ if (!cycle || second_round)
+ goto err;
+ round++;
+ reserved_until= real_increment >0 ? min_value : max_value;
+ adjust_values(reserved_until); // Fix next_free_value
+ /*
+ We have to do everything again to ensure that the given range was
+ not empty, which could happen if increment == 0
+ */
+ DBUG_RETURN(next_value(table, 1, error));
+ }
+
+ if ((*error= write(table, 0)))
+ {
+ reserved_until= org_reserved_until;
+ next_free_value= res_value;
+ }
+
+ write_unlock(table);
+ DBUG_RETURN(res_value);
+
+err:
+ write_unlock(table);
+ my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
+ table->s->table_name.str);
+ *error= ER_SEQUENCE_RUN_OUT;
+ all_values_used= 1;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ The following functions is to detect if a table has been dropped
+ and re-created since last call to PREVIOUS VALUE.
+
+ This is needed as we don't delete dropped sequences from THD->sequence
+ for DROP TABLE.
+*/
+
+bool SEQUENCE_LAST_VALUE::check_version(TABLE *table)
+{
+ DBUG_ASSERT(table->s->tabledef_version.length == MY_UUID_SIZE);
+ return memcmp(table->s->tabledef_version.str, table_version,
+ MY_UUID_SIZE) != 0;
+}
+
+void SEQUENCE_LAST_VALUE::set_version(TABLE *table)
+{
+ memcpy(table_version, table->s->tabledef_version.str, MY_UUID_SIZE);
+}
+
+/**
+ Set the next value for sequence
+
+ @param in table Sequence table
+ @param in next_val Next free value
+ @param in next_round Round for 'next_value' (in cace of cycles)
+ @param in is_used 1 if next_val is already used
+
+  @retval 0 ok, value adjusted
+ 1 value was less than current value or
+ error when storing value
+
+ @comment
+ A new value is set only if "nextval,next_round" is less than
+ "next_free_value,round". This is needed as in replication
+ setvalue() calls may come out to the slave out-of-order.
+ Storing only the highest value ensures that sequence object will always
+ contain the highest used value when the slave is promoted to a master.
+*/
+
+bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
+ bool is_used)
+{
+ bool error= 1;
+ bool needs_to_be_stored= 0;
+ longlong org_reserved_until= reserved_until;
+ longlong org_next_free_value= next_free_value;
+ ulonglong org_round= round;
+ DBUG_ENTER("SEQUENCE::set_value");
+
+ write_lock(table);
+ if (is_used)
+ next_val= increment_value(next_val);
+
+ if (round > next_round)
+ goto end;
+ if (round == next_round)
+ {
+ if (real_increment > 0 ?
+ next_val < next_free_value :
+ next_val > next_free_value)
+ goto end;
+ if (next_val == next_free_value)
+ {
+ error= 0;
+ goto end;
+ }
+ }
+ else if (cycle == 0)
+ goto end; // round < next_round && no cycles
+ else
+ needs_to_be_stored= 1;
+
+ round= next_round;
+ adjust_values(next_val);
+ if ((real_increment > 0 ?
+ next_free_value > reserved_until :
+ next_free_value < reserved_until) ||
+ needs_to_be_stored)
+ {
+ reserved_until= next_free_value;
+ if (write(table, 0))
+ {
+ reserved_until= org_reserved_until;
+ next_free_value= org_next_free_value;
+ round= org_round;
+ goto end;
+ }
+ }
+ error= 0;
+
+end:
+ write_unlock(table);
+ DBUG_RETURN(error);
+}
+
+
+bool Sql_cmd_alter_sequence::execute(THD *thd)
+{
+ int error= 0;
+ int trapped_errors= 0;
+ LEX *lex= thd->lex;
+ TABLE_LIST *first_table= lex->query_tables;
+ TABLE *table;
+ sequence_definition *new_seq= lex->create_info.seq_create_info;
+ SEQUENCE *seq;
+ No_such_table_error_handler no_such_table_handler;
+ DBUG_ENTER("Sql_cmd_alter_sequence::execute");
+
+ if (check_access(thd, ALTER_ACL, first_table->db,
+ &first_table->grant.privilege,
+ &first_table->grant.m_internal,
+ 0, 0))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+
+ if (check_grant(thd, ALTER_ACL, first_table, FALSE, UINT_MAX, FALSE))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+
+ if (lex->check_exists)
+ thd->push_internal_handler(&no_such_table_handler);
+ error= open_and_lock_tables(thd, first_table, FALSE, 0);
+ if (lex->check_exists)
+ {
+ trapped_errors= no_such_table_handler.safely_trapped_errors();
+ thd->pop_internal_handler();
+ }
+ if (error)
+ {
+ if (trapped_errors)
+ {
+ StringBuffer<FN_REFLEN> tbl_name;
+ tbl_name.append(first_table->db);
+ tbl_name.append('.');
+ tbl_name.append(first_table->table_name);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_SEQUENCES,
+ ER_THD(thd, ER_UNKNOWN_SEQUENCES),
+ tbl_name.c_ptr_safe());
+ my_ok(thd);
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_RETURN(TRUE);
+ }
+
+ table= first_table->table;
+ seq= table->s->sequence;
+ new_seq->reserved_until= seq->reserved_until;
+
+ /* Copy from old sequence those fields that the user didn't specified */
+ if (!(new_seq->used_fields & seq_field_used_increment))
+ new_seq->increment= seq->increment;
+ if (!(new_seq->used_fields & seq_field_used_min_value))
+ new_seq->min_value= seq->min_value;
+ if (!(new_seq->used_fields & seq_field_used_max_value))
+ new_seq->max_value= seq->max_value;
+ if (!(new_seq->used_fields & seq_field_used_start))
+ new_seq->start= seq->start;
+ if (!(new_seq->used_fields & seq_field_used_cache))
+ new_seq->cache= seq->cache;
+ if (!(new_seq->used_fields & seq_field_used_cycle))
+ new_seq->cycle= seq->cycle;
+
+ /* If we should restart from a new value */
+ if (new_seq->used_fields & seq_field_used_restart)
+ {
+ if (!(new_seq->used_fields & seq_field_used_restart_value))
+ new_seq->restart= new_seq->start;
+ new_seq->reserved_until= new_seq->restart;
+ }
+
+ /* Let check_and_adjust think all fields are used */
+ new_seq->used_fields= ~0;
+ if (new_seq->check_and_adjust(0))
+ {
+ my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
+ first_table->db,
+ first_table->table_name);
+ error= 1;
+ goto end;
+ }
+
+ table->s->sequence->write_lock(table);
+ if (!(error= new_seq->write(table, 1)))
+ {
+ /* Store the sequence values in table share */
+ table->s->sequence->copy(new_seq);
+ }
+ else
+ table->file->print_error(error, MYF(0));
+ table->s->sequence->write_unlock(table);
+ if (trans_commit_stmt(thd))
+ error= 1;
+ if (trans_commit_implicit(thd))
+ error= 1;
+ if (!error)
+ error= write_bin_log(thd, 1, thd->query(), thd->query_length());
+ if (!error)
+ my_ok(thd);
+
+end:
+ DBUG_RETURN(error);
+}
diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h
new file mode 100644
index 00000000000..1dc777657d5
--- /dev/null
+++ b/sql/sql_sequence.h
@@ -0,0 +1,168 @@
+/* Copyright (c) 2017, MariaDB corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef SQL_SEQUENCE_INCLUDED
+#define SQL_SEQUENCE_INCLUDED
+
+#define seq_field_used_min_value 1
+#define seq_field_used_max_value 2
+#define seq_field_used_start 4
+#define seq_field_used_increment 8
+#define seq_field_used_cache 16
+#define seq_field_used_cycle 32
+#define seq_field_used_restart 64
+#define seq_field_used_restart_value 128
+
+/* Field position in sequence table for some fields we refer to directly */
+#define NEXT_FIELD_NO 0
+#define MIN_VALUE_FIELD_NO 1
+#define ROUND_FIELD_NO 7
+
+/**
+ sequence_definition is used when defining a sequence as part of create
+*/
+
+class sequence_definition :public Sql_alloc
+{
+public:
+ sequence_definition():
+ min_value(1), max_value(LONGLONG_MAX-1), start(1), increment(1),
+ cache(1000), round(0), restart(0), cycle(0), used_fields(0)
+ {}
+ longlong reserved_until;
+ longlong min_value;
+ longlong max_value;
+ longlong start;
+ longlong increment;
+ longlong cache;
+ ulonglong round;
+ longlong restart; // alter sequence restart value
+ bool cycle;
+ uint used_fields; // Which fields where used in CREATE
+
+ bool check_and_adjust(bool set_reserved_until);
+ void store_fields(TABLE *table);
+ void read_fields(TABLE *table);
+ int write_initial_sequence(TABLE *table);
+ int write(TABLE *table, bool all_fields);
+ /* This must be called after sequence data has been updated */
+ void adjust_values(longlong next_value);
+ inline void print_dbug()
+ {
+ DBUG_PRINT("sequence", ("reserved: %lld start: %lld increment: %lld min_value: %lld max_value: %lld cache: %lld round: %lld",
+ reserved_until, start, increment, min_value,
+ max_value, cache, round));
+ }
+protected:
+ /*
+ The following values are the values from sequence_definition
+ merged with global auto_increment_offset and auto_increment_increment
+ */
+ longlong real_increment;
+ longlong next_free_value;
+};
+
+/**
+ SEQUENCE is in charge of managing the sequence values.
+ It's also responsible to generate new values and updating the sequence
+ table (engine=SQL_SEQUENCE) trough it's specialized handler interface.
+
+ If increment is 0 then the sequence will be be using
+ auto_increment_increment and auto_increment_offset variables, just like
+ AUTO_INCREMENT is using.
+*/
+
+class SEQUENCE :public sequence_definition
+{
+public:
+ enum seq_init { SEQ_UNINTIALIZED, SEQ_IN_PREPARE, SEQ_IN_ALTER,
+ SEQ_READY_TO_USE };
+ SEQUENCE();
+ ~SEQUENCE();
+ int read_initial_values(TABLE *table);
+ int read_stored_values();
+ void write_lock(TABLE *table);
+ void write_unlock(TABLE *table);
+ void read_lock(TABLE *table);
+ void read_unlock(TABLE *table);
+ void copy(sequence_definition *seq)
+ {
+ sequence_definition::operator= (*seq);
+ adjust_values(reserved_until);
+ all_values_used= 0;
+ }
+ longlong next_value(TABLE *table, bool second_round, int *error);
+ bool set_value(TABLE *table, longlong next_value, ulonglong round_arg,
+ bool is_used);
+ longlong increment_value(longlong value)
+ {
+ if (real_increment > 0)
+ {
+ if (value + real_increment > max_value ||
+ value > max_value - real_increment)
+ value= max_value + 1;
+ else
+ value+= real_increment;
+ }
+ else
+ {
+ if (value + real_increment < min_value ||
+ value < min_value - real_increment)
+ value= min_value - 1;
+ else
+ value+= real_increment;
+ }
+ return value;
+ }
+
+ bool all_values_used;
+ seq_init initialized;
+
+private:
+ TABLE *table;
+ mysql_rwlock_t mutex;
+};
+
+
+/**
+ Class to cache last value of NEXT VALUE from the sequence
+*/
+
+class SEQUENCE_LAST_VALUE
+{
+public:
+ SEQUENCE_LAST_VALUE(uchar *key_arg, uint length_arg)
+ :key(key_arg), length(length_arg)
+ {}
+ ~SEQUENCE_LAST_VALUE()
+ { my_free((void*) key); }
+ /* Returns 1 if table hasn't been dropped or re-created */
+ bool check_version(TABLE *table);
+ void set_version(TABLE *table);
+
+ const uchar *key;
+ uint length;
+ bool null_value;
+ longlong value;
+ uchar table_version[MY_UUID_SIZE];
+};
+
+
+class Create_field;
+extern bool prepare_sequence_fields(THD *thd, List<Create_field> *fields);
+extern bool check_sequence_fields(LEX *lex, List<Create_field> *fields);
+extern bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list);
+#endif /* SQL_SEQUENCE_INCLUDED */
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index 836b0563e23..bbed5ac8991 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -64,7 +64,7 @@ static int insert_server_record_into_cache(FOREIGN_SERVER *server);
static FOREIGN_SERVER *
prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options);
/* drop functions */
-static int delete_server_record(TABLE *table, LEX_STRING *name);
+static int delete_server_record(TABLE *table, LEX_CSTRING *name);
static int delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options);
/* update functions */
@@ -939,7 +939,7 @@ end:
*/
static int
-delete_server_record(TABLE *table, LEX_STRING *name)
+delete_server_record(TABLE *table, LEX_CSTRING *name)
{
int error;
DBUG_ENTER("delete_server_record");
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 229d284bc3d..fd0d11bf1bb 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -58,10 +58,11 @@
#include "lock.h" // MYSQL_OPEN_IGNORE_FLUSH
#include "debug_sync.h"
#include "keycaches.h"
-
+#include "ha_sequence.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
#endif
+
enum enum_i_s_events_fields
{
ISE_EVENT_CATALOG= 0,
@@ -93,17 +94,17 @@ enum enum_i_s_events_fields
#define USERNAME_WITH_HOST_CHAR_LENGTH (USERNAME_CHAR_LENGTH + HOSTNAME_LENGTH + 2)
-static const LEX_STRING trg_action_time_type_names[]=
+static const LEX_CSTRING trg_action_time_type_names[]=
{
- { C_STRING_WITH_LEN("BEFORE") },
- { C_STRING_WITH_LEN("AFTER") }
+ { STRING_WITH_LEN("BEFORE") },
+ { STRING_WITH_LEN("AFTER") }
};
-static const LEX_STRING trg_event_type_names[]=
+static const LEX_CSTRING trg_event_type_names[]=
{
- { C_STRING_WITH_LEN("INSERT") },
- { C_STRING_WITH_LEN("UPDATE") },
- { C_STRING_WITH_LEN("DELETE") }
+ { STRING_WITH_LEN("INSERT") },
+ { STRING_WITH_LEN("UPDATE") },
+ { STRING_WITH_LEN("DELETE") }
};
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -130,8 +131,10 @@ static void get_cs_converted_string_value(THD *thd,
#endif
static int show_create_view(THD *thd, TABLE_LIST *table, String *buff);
+static int show_create_sequence(THD *thd, TABLE_LIST *table_list,
+ String *packet);
-static const LEX_STRING *view_algorithm(TABLE_LIST *table);
+static const LEX_CSTRING *view_algorithm(TABLE_LIST *table);
bool get_lookup_field_values(THD *, COND *, TABLE_LIST *, LOOKUP_FIELD_VALUES *);
@@ -145,13 +148,13 @@ static int make_version_string(char *buf, int buf_length, uint version)
}
-static const LEX_STRING maturity_name[]={
- { C_STRING_WITH_LEN("Unknown") },
- { C_STRING_WITH_LEN("Experimental") },
- { C_STRING_WITH_LEN("Alpha") },
- { C_STRING_WITH_LEN("Beta") },
- { C_STRING_WITH_LEN("Gamma") },
- { C_STRING_WITH_LEN("Stable") }};
+static const LEX_CSTRING maturity_name[]={
+ { STRING_WITH_LEN("Unknown") },
+ { STRING_WITH_LEN("Experimental") },
+ { STRING_WITH_LEN("Alpha") },
+ { STRING_WITH_LEN("Beta") },
+ { STRING_WITH_LEN("Gamma") },
+ { STRING_WITH_LEN("Stable") }};
static my_bool show_plugins(THD *thd, plugin_ref plugin,
@@ -311,7 +314,7 @@ int fill_all_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
for (uint i=0; i < (uint) dirp->number_of_files; i++)
{
FILEINFO *file= dirp->dir_entry+i;
- LEX_STRING dl= { file->name, strlen(file->name) };
+ LEX_CSTRING dl= { file->name, strlen(file->name) };
const char *dlend= dl.str + dl.length;
const size_t so_ext_len= sizeof(SO_EXT) - 1;
@@ -384,8 +387,8 @@ exit:
static int get_geometry_column_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
CHARSET_INFO *cs= system_charset_info;
TABLE *show_table;
@@ -439,7 +442,8 @@ static int get_geometry_column_record(THD *thd, TABLE_LIST *tables,
/*G_TABLE_NAME*/
table->field[6]->store(table_name->str, table_name->length, cs);
/*G_GEOMETRY_COLUMN*/
- table->field[7]->store(field->field_name, strlen(field->field_name), cs);
+ table->field[7]->store(field->field_name.str, field->field_name.length,
+ cs);
/*STORAGE_TYPE*/
table->field[8]->store(1LL, TRUE); /*Always 1 (binary implementation)*/
/*GEOMETRY_TYPE*/
@@ -664,7 +668,7 @@ static bool skip_ignored_dir_check= TRUE;
bool
ignore_db_dirs_init()
{
- return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *),
+ return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_CSTRING *),
0, 0, MYF(0));
}
@@ -684,7 +688,7 @@ static uchar *
db_dirs_hash_get_key(const uchar *data, size_t *len_ret,
my_bool __attribute__((unused)))
{
- LEX_STRING *e= (LEX_STRING *) data;
+ LEX_CSTRING *e= (LEX_CSTRING *) data;
*len_ret= e->length;
return (uchar *) e->str;
@@ -705,7 +709,7 @@ db_dirs_hash_get_key(const uchar *data, size_t *len_ret,
bool
push_ignored_db_dir(char *path)
{
- LEX_STRING *new_elt;
+ LEX_CSTRING *new_elt;
char *new_elt_buffer;
size_t path_len= strlen(path);
@@ -714,7 +718,7 @@ push_ignored_db_dir(char *path)
// No need to normalize, it's only a directory name, not a path.
if (!my_multi_malloc(0,
- &new_elt, sizeof(LEX_STRING),
+ &new_elt, sizeof(LEX_CSTRING),
&new_elt_buffer, path_len + 1,
NullS))
return true;
@@ -736,8 +740,8 @@ push_ignored_db_dir(char *path)
void
ignore_db_dirs_reset()
{
- LEX_STRING **elt;
- while (NULL!= (elt= (LEX_STRING **) pop_dynamic(&ignore_db_dirs_array)))
+ LEX_CSTRING **elt;
+ while (NULL!= (elt= (LEX_CSTRING **) pop_dynamic(&ignore_db_dirs_array)))
if (elt && *elt)
my_free(*elt);
}
@@ -787,8 +791,7 @@ ignore_db_dirs_process_additions()
ulong i;
size_t len;
char *ptr;
- LEX_STRING *dir;
-
+ LEX_CSTRING *dir;
skip_ignored_dir_check= TRUE;
@@ -940,8 +943,8 @@ enum find_files_result {
static find_files_result
-find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db,
- const char *path, const LEX_STRING *wild)
+find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db,
+ const char *path, const LEX_CSTRING *wild)
{
MY_DIR *dirp;
Discovered_table_list tl(thd, files, wild);
@@ -1170,12 +1173,19 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list,
}
/* TODO: add environment variables show when it become possible */
- if (thd->lex->only_view && !table_list->view)
+ if (thd->lex->table_type == TABLE_TYPE_VIEW && !table_list->view)
{
my_error(ER_WRONG_OBJECT, MYF(0),
table_list->db, table_list->table_name, "VIEW");
goto exit;
}
+ else if (thd->lex->table_type == TABLE_TYPE_SEQUENCE &&
+ table_list->table->s->table_type != TABLE_TYPE_SEQUENCE)
+ {
+ my_error(ER_NOT_SEQUENCE, MYF(0),
+ table_list->db, table_list->table_name);
+ goto exit;
+ }
buffer->length(0);
@@ -1184,6 +1194,8 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list,
if ((table_list->view ?
show_create_view(thd, table_list, buffer) :
+ thd->lex->table_type == TABLE_TYPE_SEQUENCE ?
+ show_create_sequence(thd, table_list, buffer) :
show_create_table(thd, table_list, buffer, NULL, WITHOUT_DB_NAME)))
goto exit;
@@ -1317,8 +1329,8 @@ void mysqld_show_create_db_get_fields(THD *thd, List<Item> *field_list)
}
-bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname,
- LEX_STRING *orig_dbname,
+bool mysqld_show_create_db(THD *thd, LEX_CSTRING *dbname,
+ LEX_CSTRING *orig_dbname,
const DDL_options_st &options)
{
char buff[2048];
@@ -1431,7 +1443,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
for (ptr=table->field ; (field= *ptr); ptr++)
{
if (!wild || !wild[0] ||
- !wild_case_compare(system_charset_info, field->field_name,wild))
+ !wild_case_compare(system_charset_info, field->field_name.str,wild))
{
if (table_list->view)
field_list.push_back(new (mem_root)
@@ -1767,6 +1779,179 @@ static void append_create_options(THD *thd, String *packet,
packet->append(STRING_WITH_LEN(" */"));
}
+/**
+ Add table options to end of CREATE statement
+
+ @param schema_table 1 if schema table
+ @param sequence 1 if sequence. If sequence, we flush out options
+ not relevant for sequences.
+*/
+
+static void add_table_options(THD *thd, TABLE *table,
+ Table_specification_st *create_info_arg,
+ bool schema_table, bool sequence,
+ String *packet)
+{
+ sql_mode_t sql_mode= thd->variables.sql_mode;
+ TABLE_SHARE *share= table->s;
+ handlerton *hton;
+ HA_CREATE_INFO create_info;
+ bool check_options= (!(sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) &&
+ !create_info_arg);
+
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (table->part_info)
+ hton= table->part_info->default_engine_type;
+ else
+#endif
+ hton= table->file->ht;
+
+ bzero((char*) &create_info, sizeof(create_info));
+ /* Allow update_create_info to update row type, page checksums and options */
+ create_info.row_type= share->row_type;
+ create_info.page_checksum= share->page_checksum;
+ create_info.options= share->db_create_options;
+ table->file->update_create_info(&create_info);
+
+ /*
+ IF check_create_info
+ THEN add ENGINE only if it was used when creating the table
+ */
+ if (!create_info_arg ||
+ (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
+ {
+ LEX_CSTRING *engine_name= table->file->engine_name();
+
+ if (sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
+ packet->append(STRING_WITH_LEN(" TYPE="));
+ else
+ packet->append(STRING_WITH_LEN(" ENGINE="));
+
+ packet->append(engine_name->str, engine_name->length);
+ }
+
+ if (sequence)
+ goto end_options;
+
+ /*
+ Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
+ and NEXT_ID > 1 (the default). We must not print the clause
+ for engines that do not support this as it would break the
+ import of dumps, but as of this writing, the test for whether
+ AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
+ is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
+ Because of that, we do not explicitly test for the feature,
+ but may extrapolate its existence from that of an AUTO_INCREMENT column.
+ */
+
+ if (create_info.auto_increment_value > 1)
+ {
+ packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
+ packet->append_ulonglong(create_info.auto_increment_value);
+ }
+
+ if (share->table_charset && !(sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
+ share->table_type != TABLE_TYPE_SEQUENCE)
+ {
+ /*
+ IF check_create_info
+ THEN add DEFAULT CHARSET only if it was used when creating the table
+ */
+ if (!create_info_arg ||
+ (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
+ {
+ packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
+ packet->append(share->table_charset->csname);
+ if (!(share->table_charset->state & MY_CS_PRIMARY))
+ {
+ packet->append(STRING_WITH_LEN(" COLLATE="));
+ packet->append(table->s->table_charset->name);
+ }
+ }
+ }
+
+ if (share->min_rows)
+ {
+ packet->append(STRING_WITH_LEN(" MIN_ROWS="));
+ packet->append_ulonglong(share->min_rows);
+ }
+
+ if (share->max_rows && !schema_table && !sequence)
+ {
+ packet->append(STRING_WITH_LEN(" MAX_ROWS="));
+ packet->append_ulonglong(share->max_rows);
+ }
+
+ if (share->avg_row_length)
+ {
+ packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
+ packet->append_ulonglong(share->avg_row_length);
+ }
+
+ if (create_info.options & HA_OPTION_PACK_KEYS)
+ packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
+ if (create_info.options & HA_OPTION_NO_PACK_KEYS)
+ packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
+ if (share->db_create_options & HA_OPTION_STATS_PERSISTENT)
+ packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=1"));
+ if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT)
+ packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=0"));
+ if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON)
+ packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=1"));
+ else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF)
+ packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=0"));
+ if (share->stats_sample_pages != 0)
+ {
+ packet->append(STRING_WITH_LEN(" STATS_SAMPLE_PAGES="));
+ packet->append_ulonglong(share->stats_sample_pages);
+ }
+
+ /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
+ if (create_info.options & HA_OPTION_CHECKSUM)
+ packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
+ if (create_info.page_checksum != HA_CHOICE_UNDEF)
+ {
+ packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM="));
+ packet->append(ha_choice_values[create_info.page_checksum], 1);
+ }
+ if (create_info.options & HA_OPTION_DELAY_KEY_WRITE)
+ packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
+ if (create_info.row_type != ROW_TYPE_DEFAULT)
+ {
+ packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
+ packet->append(ha_row_type[(uint) create_info.row_type]);
+ }
+ if (share->transactional != HA_CHOICE_UNDEF)
+ {
+ packet->append(STRING_WITH_LEN(" TRANSACTIONAL="));
+ packet->append(ha_choice_values[(uint) share->transactional], 1);
+ }
+ if (share->table_type == TABLE_TYPE_SEQUENCE)
+ packet->append(STRING_WITH_LEN(" SEQUENCE=1"));
+ if (table->s->key_block_size)
+ {
+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
+ packet->append_ulonglong(table->s->key_block_size);
+ }
+ table->file->append_create_info(packet);
+
+end_options:
+ if (share->comment.length)
+ {
+ packet->append(STRING_WITH_LEN(" COMMENT="));
+ append_unescaped(packet, share->comment.str, share->comment.length);
+ }
+ if (share->connect_string.length)
+ {
+ packet->append(STRING_WITH_LEN(" CONNECTION="));
+ append_unescaped(packet, share->connect_string.str, share->connect_string.length);
+ }
+ append_create_options(thd, packet, share->option_list, check_options,
+ hton->table_options);
+ append_directory(thd, packet, "DATA", create_info.data_file_name);
+ append_directory(thd, packet, "INDEX", create_info.index_file_name);
+}
+
/*
Build a CREATE TABLE statement for a table.
@@ -1796,7 +1981,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
enum_with_db_name with_db_name)
{
List<Item> field_list;
- char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
+ char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
const char *alias;
String type;
String def_value;
@@ -1804,9 +1989,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
uint primary_key;
KEY *key_info;
TABLE *table= table_list->table;
- handler *file= table->file;
TABLE_SHARE *share= table->s;
- HA_CREATE_INFO create_info;
sql_mode_t sql_mode= thd->variables.sql_mode;
bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE |
MODE_MSSQL | MODE_DB2 |
@@ -1817,8 +2000,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
!foreign_db_mode;
bool check_options= !(sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) &&
!create_info_arg;
- handlerton *hton;
my_bitmap_map *old_map;
+ handlerton *hton;
int error= 0;
DBUG_ENTER("show_create_table");
DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
@@ -1828,7 +2011,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
hton= table->part_info->default_engine_type;
else
#endif
- hton= file->ht;
+ hton= table->file->ht;
restore_record(table, s->default_values); // Get empty record
@@ -1864,7 +2047,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
*/
if (with_db_name == WITH_DB_NAME)
{
- const LEX_STRING *const db=
+ const LEX_CSTRING *const db=
table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db;
if (!thd->db || strcmp(db->str, thd->db))
{
@@ -1890,7 +2073,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(",\n"));
packet->append(STRING_WITH_LEN(" "));
- append_identifier(thd,packet,field->field_name, strlen(field->field_name));
+ append_identifier(thd,packet,field->field_name.str,
+ field->field_name.length);
packet->append(' ');
type.set(tmp, sizeof(tmp), system_charset_info);
@@ -1977,12 +2161,6 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
}
key_info= table->key_info;
- bzero((char*) &create_info, sizeof(create_info));
- /* Allow update_create_info to update row type, page checksums and options */
- create_info.row_type= share->row_type;
- create_info.page_checksum= share->page_checksum;
- create_info.options= share->db_create_options;
- file->update_create_info(&create_info);
primary_key= share->primary_key;
for (uint i=0 ; i < share->keys ; i++,key_info++)
@@ -2020,8 +2198,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(',');
if (key_part->field)
- append_identifier(thd,packet,key_part->field->field_name,
- strlen(key_part->field->field_name));
+ append_identifier(thd,packet, key_part->field->field_name.str,
+ key_part->field->field_name.length);
if (key_part->field &&
(key_part->length !=
table->field[key_part->fieldnr-1]->key_length() &&
@@ -2035,7 +2213,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
store_key_options(thd, packet, table, key_info);
if (key_info->parser)
{
- LEX_STRING *parser_name= plugin_name(key_info->parser);
+ LEX_CSTRING *parser_name= plugin_name(key_info->parser);
packet->append(STRING_WITH_LEN(" /*!50100 WITH PARSER "));
append_identifier(thd, packet, parser_name->str, parser_name->length);
packet->append(STRING_WITH_LEN(" */ "));
@@ -2049,10 +2227,10 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
to the CREATE TABLE statement
*/
- if ((for_str= file->get_foreign_key_create_info()))
+ if ((for_str= table->file->get_foreign_key_create_info()))
{
packet->append(for_str, strlen(for_str));
- file->free_foreign_key_create_info(for_str);
+ table->file->free_foreign_key_create_info(for_str);
}
/* Add table level check constraints */
@@ -2079,146 +2257,9 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN("\n)"));
if (show_table_options)
- {
- /*
- IF check_create_info
- THEN add ENGINE only if it was used when creating the table
- */
- if (!create_info_arg ||
- (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
- {
- if (sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
- packet->append(STRING_WITH_LEN(" TYPE="));
- else
- packet->append(STRING_WITH_LEN(" ENGINE="));
- packet->append(hton_name(hton));
- }
-
- /*
- Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
- and NEXT_ID > 1 (the default). We must not print the clause
- for engines that do not support this as it would break the
- import of dumps, but as of this writing, the test for whether
- AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
- is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
- Because of that, we do not explicitly test for the feature,
- but may extrapolate its existence from that of an AUTO_INCREMENT column.
- */
-
- if (create_info.auto_increment_value > 1)
- {
- char *end;
- packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
- end= longlong10_to_str(create_info.auto_increment_value, buff,10);
- packet->append(buff, (uint) (end - buff));
- }
-
- if (share->table_charset && !(sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
- {
- /*
- IF check_create_info
- THEN add DEFAULT CHARSET only if it was used when creating the table
- */
- if (!create_info_arg ||
- (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
- {
- packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
- packet->append(share->table_charset->csname);
- if (!(share->table_charset->state & MY_CS_PRIMARY))
- {
- packet->append(STRING_WITH_LEN(" COLLATE="));
- packet->append(table->s->table_charset->name);
- }
- }
- }
+ add_table_options(thd, table, create_info_arg,
+ table_list->schema_table != 0, 0, packet);
- if (share->min_rows)
- {
- char *end;
- packet->append(STRING_WITH_LEN(" MIN_ROWS="));
- end= longlong10_to_str(share->min_rows, buff, 10);
- packet->append(buff, (uint) (end- buff));
- }
-
- if (share->max_rows && !table_list->schema_table)
- {
- char *end;
- packet->append(STRING_WITH_LEN(" MAX_ROWS="));
- end= longlong10_to_str(share->max_rows, buff, 10);
- packet->append(buff, (uint) (end - buff));
- }
-
- if (share->avg_row_length)
- {
- char *end;
- packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
- end= longlong10_to_str(share->avg_row_length, buff,10);
- packet->append(buff, (uint) (end - buff));
- }
-
- if (create_info.options & HA_OPTION_PACK_KEYS)
- packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
- if (create_info.options & HA_OPTION_NO_PACK_KEYS)
- packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
- if (share->db_create_options & HA_OPTION_STATS_PERSISTENT)
- packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=1"));
- if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT)
- packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=0"));
- if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON)
- packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=1"));
- else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF)
- packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=0"));
- if (share->stats_sample_pages != 0)
- {
- char *end;
- packet->append(STRING_WITH_LEN(" STATS_SAMPLE_PAGES="));
- end= longlong10_to_str(share->stats_sample_pages, buff, 10);
- packet->append(buff, (uint) (end - buff));
- }
-
- /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
- if (create_info.options & HA_OPTION_CHECKSUM)
- packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
- if (create_info.page_checksum != HA_CHOICE_UNDEF)
- {
- packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM="));
- packet->append(ha_choice_values[create_info.page_checksum], 1);
- }
- if (create_info.options & HA_OPTION_DELAY_KEY_WRITE)
- packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
- if (create_info.row_type != ROW_TYPE_DEFAULT)
- {
- packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
- packet->append(ha_row_type[(uint) create_info.row_type]);
- }
- if (share->transactional != HA_CHOICE_UNDEF)
- {
- packet->append(STRING_WITH_LEN(" TRANSACTIONAL="));
- packet->append(ha_choice_values[(uint) share->transactional], 1);
- }
- if (table->s->key_block_size)
- {
- char *end;
- packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
- end= longlong10_to_str(table->s->key_block_size, buff, 10);
- packet->append(buff, (uint) (end - buff));
- }
- table->file->append_create_info(packet);
- if (share->comment.length)
- {
- packet->append(STRING_WITH_LEN(" COMMENT="));
- append_unescaped(packet, share->comment.str, share->comment.length);
- }
- if (share->connect_string.length)
- {
- packet->append(STRING_WITH_LEN(" CONNECTION="));
- append_unescaped(packet, share->connect_string.str, share->connect_string.length);
- }
- append_create_options(thd, packet, share->option_list, check_options,
- hton->table_options);
- append_directory(thd, packet, "DATA", create_info.data_file_name);
- append_directory(thd, packet, "INDEX", create_info.index_file_name);
- }
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
if (table->part_info &&
@@ -2315,11 +2356,11 @@ void view_store_options(THD *thd, TABLE_LIST *table, String *buff)
Returns ALGORITHM clause of a view
*/
-static const LEX_STRING *view_algorithm(TABLE_LIST *table)
+static const LEX_CSTRING *view_algorithm(TABLE_LIST *table)
{
- static const LEX_STRING undefined= { C_STRING_WITH_LEN("UNDEFINED") };
- static const LEX_STRING merge= { C_STRING_WITH_LEN("MERGE") };
- static const LEX_STRING temptable= { C_STRING_WITH_LEN("TEMPTABLE") };
+ static const LEX_CSTRING undefined= { STRING_WITH_LEN("UNDEFINED") };
+ static const LEX_CSTRING merge= { STRING_WITH_LEN("MERGE") };
+ static const LEX_CSTRING temptable= { STRING_WITH_LEN("TEMPTABLE") };
switch (table->algorithm) {
case VIEW_ALGORITHM_TMPTABLE:
return &temptable;
@@ -2343,8 +2384,8 @@ static const LEX_STRING *view_algorithm(TABLE_LIST *table)
definer_host [in] host name part of definer
*/
-void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
- const LEX_STRING *definer_host)
+void append_definer(THD *thd, String *buffer, const LEX_CSTRING *definer_user,
+ const LEX_CSTRING *definer_host)
{
buffer->append(STRING_WITH_LEN("DEFINER="));
append_identifier(thd, buffer, definer_user->str, definer_user->length);
@@ -2424,6 +2465,55 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff)
}
+static int show_create_sequence(THD *thd, TABLE_LIST *table_list,
+ String *packet)
+{
+ TABLE *table= table_list->table;
+ SEQUENCE *seq= table->s->sequence;
+ LEX_CSTRING alias;
+ sql_mode_t sql_mode= thd->variables.sql_mode;
+ bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE |
+ MODE_MSSQL | MODE_DB2 |
+ MODE_MAXDB | MODE_ANSI);
+ bool show_table_options= !(sql_mode & MODE_NO_TABLE_OPTIONS) &&
+ !foreign_db_mode;
+
+ if (lower_case_table_names == 2)
+ {
+ alias.str= table->alias.c_ptr();
+ alias.length= table->alias.length();
+ }
+ else
+ alias= table->s->table_name;
+
+ packet->append(STRING_WITH_LEN("CREATE SEQUENCE "));
+ append_identifier(thd, packet, alias.str, alias.length);
+ packet->append(STRING_WITH_LEN(" start with "));
+ packet->append_longlong(seq->start);
+ packet->append(STRING_WITH_LEN(" minvalue "));
+ packet->append_longlong(seq->min_value);
+ packet->append(STRING_WITH_LEN(" maxvalue "));
+ packet->append_longlong(seq->max_value);
+ packet->append(STRING_WITH_LEN(" increment by "));
+ packet->append_longlong(seq->increment);
+ if (seq->cache)
+ {
+ packet->append(STRING_WITH_LEN(" cache "));
+ packet->append_longlong(seq->cache);
+ }
+ else
+ packet->append(STRING_WITH_LEN(" nocache"));
+ if (seq->cycle)
+ packet->append(STRING_WITH_LEN(" cycle"));
+ else
+ packet->append(STRING_WITH_LEN(" nocycle"));
+
+ if (show_table_options)
+ add_table_options(thd, table, 0, 0, 1, packet);
+ return 0;
+}
+
+
/****************************************************************************
Return info about all processes
returns for each thread: thread id, user, host, db, command, info
@@ -2728,8 +2818,9 @@ int select_result_text_buffer::append_row(List<Item> &items, bool send_names)
if (send_names)
{
- data_ptr= item->name;
- data_len= strlen(item->name);
+ DBUG_ASSERT(strlen(item->name.str) == item->name.length);
+ data_ptr= item->name.str;
+ data_len= item->name.length;
}
else
{
@@ -2885,7 +2976,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
}
else
{
- my_error(ER_NO_SUCH_THREAD, MYF(0), thread_id);
+ my_error(ER_NO_SUCH_THREAD, MYF(0), (ulong) thread_id);
DBUG_RETURN(1);
}
}
@@ -3251,7 +3342,7 @@ const char* get_one_variable(THD *thd,
{
sys_var *var= (sys_var *) value;
show_type= var->show_type();
- value= var->value_ptr(thd, value_type, &null_lex_str);
+ value= var->value_ptr(thd, value_type, &null_clex_str);
*charset= var->charset(thd);
}
@@ -3555,10 +3646,10 @@ bool schema_table_store_record(THD *thd, TABLE *table)
static int make_table_list(THD *thd, SELECT_LEX *sel,
- LEX_STRING *db_name, LEX_STRING *table_name)
+ LEX_CSTRING *db_name, LEX_CSTRING *table_name)
{
Table_ident *table_ident;
- table_ident= new Table_ident(thd, *db_name, *table_name, 1);
+ table_ident= new Table_ident(thd, db_name, table_name, 1);
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, MDL_SHARED_READ))
return 1;
return 0;
@@ -3629,8 +3720,8 @@ bool get_lookup_value(THD *thd, Item_func *item_func,
/* Lookup value is database name */
if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
- (uchar *) item_field->field_name,
- strlen(item_field->field_name)))
+ (uchar *) item_field->field_name.str,
+ item_field->field_name.length))
{
thd->make_lex_string(&lookup_field_vals->db_value,
tmp_str->ptr(), tmp_str->length());
@@ -3638,8 +3729,8 @@ bool get_lookup_value(THD *thd, Item_func *item_func,
/* Lookup value is table name */
else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2,
strlen(field_name2),
- (uchar *) item_field->field_name,
- strlen(item_field->field_name)))
+ (uchar *) item_field->field_name.str,
+ item_field->field_name.length))
{
thd->make_lex_string(&lookup_field_vals->table_value,
tmp_str->ptr(), tmp_str->length());
@@ -3724,11 +3815,11 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
field_info[schema_table->idx_field2].field_name : "";
if (table->table != item_field->field->table ||
(cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
- (uchar *) item_field->field_name,
- strlen(item_field->field_name)) &&
+ (uchar *) item_field->field_name.str,
+ item_field->field_name.length) &&
cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
- (uchar *) item_field->field_name,
- strlen(item_field->field_name))))
+ (uchar *) item_field->field_name.str,
+ item_field->field_name.length)))
return 0;
}
else if (item->type() == Item::REF_ITEM)
@@ -3870,10 +3961,12 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
are allocating a new memory buffer for these strings.
*/
if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0])
- my_casedn_str(system_charset_info, lookup_field_values->db_value.str);
+ my_casedn_str(system_charset_info,
+ (char*) lookup_field_values->db_value.str);
if (lookup_field_values->table_value.str &&
lookup_field_values->table_value.str[0])
- my_casedn_str(system_charset_info, lookup_field_values->table_value.str);
+ my_casedn_str(system_charset_info,
+ (char*) lookup_field_values->table_value.str);
}
return rc;
@@ -3902,8 +3995,8 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
non-zero error
*/
-int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files,
- LOOKUP_FIELD_VALUES *lookup_field_vals)
+static int make_db_list(THD *thd, Dynamic_array<LEX_CSTRING*> *files,
+ LOOKUP_FIELD_VALUES *lookup_field_vals)
{
if (lookup_field_vals->wild_db_value)
{
@@ -3960,13 +4053,13 @@ int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files,
*/
if (files->append_val(&INFORMATION_SCHEMA_NAME))
return 1;
- return find_files(thd, files, 0, mysql_data_home, &null_lex_str);
+ return find_files(thd, files, 0, mysql_data_home, &null_clex_str);
}
struct st_add_schema_table
{
- Dynamic_array<LEX_STRING*> *files;
+ Dynamic_array<LEX_CSTRING*> *files;
const char *wild;
};
@@ -3974,9 +4067,9 @@ struct st_add_schema_table
static my_bool add_schema_table(THD *thd, plugin_ref plugin,
void* p_data)
{
- LEX_STRING *file_name= 0;
+ LEX_CSTRING *file_name= 0;
st_add_schema_table *data= (st_add_schema_table *)p_data;
- Dynamic_array<LEX_STRING*> *file_list= data->files;
+ Dynamic_array<LEX_CSTRING*> *file_list= data->files;
const char *wild= data->wild;
ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
DBUG_ENTER("add_schema_table");
@@ -3996,18 +4089,18 @@ static my_bool add_schema_table(THD *thd, plugin_ref plugin,
DBUG_RETURN(0);
}
- if ((file_name= thd->make_lex_string(schema_table->table_name,
- strlen(schema_table->table_name))) &&
+ if ((file_name= thd->make_clex_string(schema_table->table_name,
+ strlen(schema_table->table_name))) &&
!file_list->append(file_name))
DBUG_RETURN(0);
DBUG_RETURN(1);
}
-int schema_tables_add(THD *thd, Dynamic_array<LEX_STRING*> *files,
+int schema_tables_add(THD *thd, Dynamic_array<LEX_CSTRING*> *files,
const char *wild)
{
- LEX_STRING *file_name= 0;
+ LEX_CSTRING *file_name;
ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
st_add_schema_table add_data;
DBUG_ENTER("schema_tables_add");
@@ -4029,8 +4122,8 @@ int schema_tables_add(THD *thd, Dynamic_array<LEX_STRING*> *files,
continue;
}
if ((file_name=
- thd->make_lex_string(tmp_schema_table->table_name,
- strlen(tmp_schema_table->table_name))) &&
+ thd->make_clex_string(tmp_schema_table->table_name,
+ strlen(tmp_schema_table->table_name))) &&
!files->append(file_name))
continue;
DBUG_RETURN(1);
@@ -4065,9 +4158,9 @@ int schema_tables_add(THD *thd, Dynamic_array<LEX_STRING*> *files,
*/
static int
-make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names,
+make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names,
LEX *lex, LOOKUP_FIELD_VALUES *lookup_field_vals,
- LEX_STRING *db_name)
+ LEX_CSTRING *db_name)
{
char path[FN_REFLEN + 1];
build_table_filename(path, sizeof(path) - 1, db_name->str, "", "", 0);
@@ -4084,13 +4177,13 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names,
}
if (db_name == &INFORMATION_SCHEMA_NAME)
{
- LEX_STRING *name;
+ LEX_CSTRING *name;
ST_SCHEMA_TABLE *schema_table=
find_schema_table(thd, lookup_field_vals->table_value.str);
if (schema_table && !schema_table->hidden)
{
- if (!(name= thd->make_lex_string(schema_table->table_name,
- strlen(schema_table->table_name))) ||
+ if (!(name= thd->make_clex_string(schema_table->table_name,
+ strlen(schema_table->table_name))) ||
table_names->append(name))
return 1;
}
@@ -4135,16 +4228,17 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names,
static void get_table_engine_for_i_s(THD *thd, char *buf, TABLE_LIST *tl,
- LEX_STRING *db, LEX_STRING *table)
+ LEX_CSTRING *db, LEX_CSTRING *table)
{
- LEX_STRING engine_name= { buf, 0 };
+ LEX_CSTRING engine_name= { buf, 0 };
if (thd->get_stmt_da()->sql_errno() == ER_UNKNOWN_STORAGE_ENGINE)
{
char path[FN_REFLEN];
build_table_filename(path, sizeof(path) - 1,
db->str, table->str, reg_ext, 0);
- if (dd_frm_type(thd, path, &engine_name) == FRMTYPE_TABLE)
+ bool is_sequence;
+ if (dd_frm_type(thd, path, &engine_name, &is_sequence) == TABLE_TYPE_NORMAL)
tl->option= engine_name.str;
}
}
@@ -4174,8 +4268,8 @@ static void get_table_engine_for_i_s(THD *thd, char *buf, TABLE_LIST *tl,
static bool
fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
TABLE *table, ST_SCHEMA_TABLE *schema_table,
- LEX_STRING *orig_db_name,
- LEX_STRING *orig_table_name,
+ LEX_CSTRING *orig_db_name,
+ LEX_CSTRING *orig_table_name,
Open_tables_backup *open_tables_state_backup,
bool can_deadlock)
{
@@ -4183,7 +4277,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
Query_arena::STMT_CONVENTIONAL_EXECUTION),
backup_arena, *old_arena;
LEX *old_lex= thd->lex, temp_lex, *lex;
- LEX_STRING db_name, table_name;
+ LEX_CSTRING db_name, table_name;
TABLE_LIST *table_list;
bool result= true;
DBUG_ENTER("fill_schema_table_by_open");
@@ -4208,6 +4302,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
/* Prepare temporary LEX. */
thd->lex= lex= &temp_lex;
lex_start(thd);
+ lex->sql_command= old_lex->sql_command;
/* Disable constant subquery evaluation as we won't be locking tables. */
lex->context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
@@ -4260,26 +4355,8 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
table_list->i_s_requested_object= schema_table->i_s_requested_object;
}
- /*
- Let us set fake sql_command so views won't try to merge
- themselves into main statement. If we don't do this,
- SELECT * from information_schema.xxxx will cause problems.
- SQLCOM_SHOW_FIELDS is used because it satisfies
- 'only_view_structure()'.
- */
- lex->sql_command= SQLCOM_SHOW_FIELDS;
- result= (thd->open_temporary_tables(table_list) ||
- open_normal_and_derived_tables(thd, table_list,
- (MYSQL_OPEN_IGNORE_FLUSH |
- MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
- (can_deadlock ?
- MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)),
- DT_INIT | DT_PREPARE | DT_CREATE));
- /*
- Restore old value of sql_command back as it is being looked at in
- process_table() function.
- */
- lex->sql_command= old_lex->sql_command;
+ DBUG_ASSERT(thd->lex == lex);
+ result= open_tables_only_view_structure(thd, table_list, can_deadlock);
DEBUG_SYNC(thd, "after_open_table_ignore_flush");
@@ -4296,7 +4373,8 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
*/
if (!is_show_fields_or_keys && result &&
(thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE ||
- thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT))
+ thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT ||
+ thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE))
{
/*
Hide error for a non-existing table.
@@ -4366,7 +4444,8 @@ end:
*/
static int fill_schema_table_names(THD *thd, TABLE_LIST *tables,
- LEX_STRING *db_name, LEX_STRING *table_name)
+ LEX_CSTRING *db_name,
+ LEX_CSTRING *table_name)
{
TABLE *table= tables->table;
if (db_name == &INFORMATION_SCHEMA_NAME)
@@ -4378,10 +4457,14 @@ static int fill_schema_table_names(THD *thd, TABLE_LIST *tables,
{
CHARSET_INFO *cs= system_charset_info;
handlerton *hton;
- if (ha_table_exists(thd, db_name->str, table_name->str, &hton))
+ bool is_sequence;
+ if (ha_table_exists(thd, db_name->str, table_name->str, &hton,
+ &is_sequence))
{
if (hton == view_pseudo_hton)
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
+ else if (is_sequence)
+ table->field[3]->store(STRING_WITH_LEN("SEQUENCE"), cs);
else
table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
}
@@ -4531,8 +4614,8 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table,
static int fill_schema_table_from_frm(THD *thd, TABLE *table,
ST_SCHEMA_TABLE *schema_table,
- LEX_STRING *db_name,
- LEX_STRING *table_name,
+ LEX_CSTRING *db_name,
+ LEX_CSTRING *table_name,
Open_tables_backup *open_tables_state_backup,
bool can_deadlock)
{
@@ -4618,7 +4701,8 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
if (!share)
{
if (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE ||
- thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT)
+ thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT ||
+ thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE)
{
res= 0;
}
@@ -4757,7 +4841,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
IS_table_read_plan *plan= tables->is_table_read_plan;
enum enum_schema_tables schema_table_idx;
- Dynamic_array<LEX_STRING*> db_names;
+ Dynamic_array<LEX_CSTRING*> db_names;
Item *partial_cond= plan->partial_cond;
int error= 1;
Open_tables_backup open_tables_state_backup;
@@ -4795,7 +4879,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
*/
if (lsel && lsel->table_list.first)
{
- LEX_STRING db_name, table_name;
+ LEX_CSTRING db_name, table_name;
db_name.str= lsel->table_list.first->db;
db_name.length= lsel->table_list.first->db_length;
@@ -4830,7 +4914,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
goto err;
for (size_t i=0; i < db_names.elements(); i++)
{
- LEX_STRING *db_name= db_names.at(i);
+ LEX_CSTRING *db_name= db_names.at(i);
DBUG_ASSERT(db_name->length <= NAME_LEN);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!(check_access(thd, SELECT_ACL, db_name->str,
@@ -4840,7 +4924,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0))
#endif
{
- Dynamic_array<LEX_STRING*> table_names;
+ Dynamic_array<LEX_CSTRING*> table_names;
int res= make_table_name_list(thd, &table_names, lex,
&plan->lookup_field_vals, db_name);
if (res == 2) /* Not fatal error, continue */
@@ -4850,7 +4934,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
for (size_t i=0; i < table_names.elements(); i++)
{
- LEX_STRING *table_name= table_names.at(i);
+ LEX_CSTRING *table_name= table_names.at(i);
DBUG_ASSERT(table_name->length <= NAME_LEN);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -4933,7 +5017,7 @@ err:
}
-bool store_schema_shemata(THD* thd, TABLE *table, LEX_STRING *db_name,
+bool store_schema_shemata(THD* thd, TABLE *table, LEX_CSTRING *db_name,
CHARSET_INFO *cs)
{
restore_record(table, s->default_values);
@@ -4953,7 +5037,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
*/
LOOKUP_FIELD_VALUES lookup_field_vals;
- Dynamic_array<LEX_STRING*> db_names;
+ Dynamic_array<LEX_CSTRING*> db_names;
Schema_specification_st create;
TABLE *table= tables->table;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -4989,7 +5073,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
for (size_t i=0; i < db_names.elements(); i++)
{
- LEX_STRING *db_name= db_names.at(i);
+ LEX_CSTRING *db_name= db_names.at(i);
DBUG_ASSERT(db_name->length <= NAME_LEN);
if (db_name == &INFORMATION_SCHEMA_NAME)
{
@@ -5018,8 +5102,8 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
const char *tmp_buff;
MYSQL_TIME time;
@@ -5061,7 +5145,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
String str(option_buff,sizeof(option_buff), system_charset_info);
TABLE *show_table= tables->table;
TABLE_SHARE *share= show_table->s;
- handler *file= show_table->file;
+ handler *file= show_table->db_stat ? show_table->file : 0;
handlerton *tmp_db_type= share->db_type();
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool is_partitioned= FALSE;
@@ -5071,6 +5155,8 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
else if (share->tmp_table)
table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
+ else if (share->table_type == TABLE_TYPE_SEQUENCE)
+ table->field[3]->store(STRING_WITH_LEN("SEQUENCE"), cs);
else
table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
@@ -5358,7 +5444,7 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
field->real_type() == MYSQL_TYPE_STRING) // For binary type
{
uint32 octet_max_length= field->max_display_length();
- if (is_blob && octet_max_length != (uint32) 4294967295U)
+ if (is_blob && octet_max_length != (uint32) UINT_MAX32)
octet_max_length /= field->charset()->mbmaxlen;
longlong char_max_len= is_blob ?
(longlong) octet_max_length / field->charset()->mbminlen :
@@ -5445,8 +5531,8 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
LEX *lex= thd->lex;
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
@@ -5489,7 +5575,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
DEBUG_SYNC(thd, "get_schema_column");
if (wild && wild[0] &&
- wild_case_compare(system_charset_info, field->field_name,wild))
+ wild_case_compare(system_charset_info, field->field_name.str, wild))
continue;
count++;
@@ -5502,7 +5588,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
&tables->grant.privilege, 0, 0, MY_TEST(tables->schema_table));
col_access= get_column_grant(thd, &tables->grant,
db_name->str, table_name->str,
- field->field_name) & COL_ACLS;
+ field->field_name.str) & COL_ACLS;
if (!tables->schema_table && !col_access)
continue;
char *end= tmp;
@@ -5520,7 +5606,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
table->field[0]->store(STRING_WITH_LEN("def"), cs);
table->field[1]->store(db_name->str, db_name->length, cs);
table->field[2]->store(table_name->str, table_name->length, cs);
- table->field[3]->store(field->field_name, strlen(field->field_name),
+ table->field[3]->store(field->field_name.str, field->field_name.length,
cs);
table->field[4]->store((longlong) count, TRUE);
@@ -5633,13 +5719,13 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin,
if (!(hton->flags & HTON_HIDDEN))
{
- LEX_STRING *name= plugin_name(plugin);
+ LEX_CSTRING *name= plugin_name(plugin);
if (!(wild && wild[0] &&
wild_case_compare(scs, name->str,wild)))
{
- LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") },
- { C_STRING_WITH_LEN("YES") }};
- LEX_STRING *tmp;
+ LEX_CSTRING yesno[2]= {{ STRING_WITH_LEN("NO") },
+ { STRING_WITH_LEN("YES") }};
+ LEX_CSTRING *tmp;
const char *option_name= show_comp_option_name[(int) hton->state];
restore_record(table, s->default_values);
@@ -5850,7 +5936,8 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE],
&tmp_string);
table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs);
- field= sp->m_return_field_def.make_field(&share, thd->mem_root, "");
+ field= sp->m_return_field_def.make_field(&share, thd->mem_root,
+ &empty_clex_str);
field->table= &tbl;
tbl.in_use= thd;
store_column_type(table, field, cs, 6);
@@ -5898,7 +5985,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs);
field= spvar->field_def.make_field(&share, thd->mem_root,
- spvar->name.str);
+ &spvar->name);
field->table= &tbl;
tbl.in_use= thd;
store_column_type(table, field, cs, 6);
@@ -5989,7 +6076,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
bzero((char*) &tbl, sizeof(TABLE));
(void) build_table_filename(path, sizeof(path), "", "", "", 0);
init_tmp_table_share(thd, &share, "", 0, "", path);
- field= sp->m_return_field_def.make_field(&share, thd->mem_root, "");
+ field= sp->m_return_field_def.make_field(&share, thd->mem_root,
+ &empty_clex_str);
field->table= &tbl;
tbl.in_use= thd;
store_column_type(table, field, cs, 5);
@@ -6115,8 +6203,8 @@ err:
static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
CHARSET_INFO *cs= system_charset_info;
DBUG_ENTER("get_schema_stat_record");
@@ -6151,7 +6239,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
{
KEY_PART_INFO *key_part= key_info->key_part;
- const char *str;
+ LEX_CSTRING *str;
+ LEX_CSTRING unknown= {STRING_WITH_LEN("?unknown field?") };
for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
{
restore_record(table, s->default_values);
@@ -6163,9 +6252,9 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
table->field[4]->store(db_name->str, db_name->length, cs);
table->field[5]->store(key_info->name, strlen(key_info->name), cs);
table->field[6]->store((longlong) (j+1), TRUE);
- str=(key_part->field ? key_part->field->field_name :
- "?unknown field?");
- table->field[7]->store(str, strlen(str), cs);
+ str= (key_part->field ? &key_part->field->field_name :
+ &unknown);
+ table->field[7]->store(str->str, str->length, cs);
if (show_table->file)
{
if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
@@ -6183,8 +6272,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
table->field[9]->store((longlong) records, TRUE);
table->field[9]->set_notnull();
}
- str= show_table->file->index_type(i);
- table->field[13]->store(str, strlen(str), cs);
+ const char *tmp= show_table->file->index_type(i);
+ table->field[13]->store(tmp, strlen(tmp), cs);
}
if (!(key_info->flags & HA_FULLTEXT) &&
(key_part->field &&
@@ -6219,8 +6308,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
CHARSET_INFO *cs= system_charset_info;
char definer[USER_HOST_BUFF_SIZE];
@@ -6363,9 +6452,10 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
}
-bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
- LEX_STRING *table_name, const char *key_name,
- uint key_len, const char *con_type, uint con_len)
+static bool
+store_constraints(THD *thd, TABLE *table, const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name, const char *key_name,
+ uint key_len, const char *con_type, uint con_len)
{
CHARSET_INFO *cs= system_charset_info;
restore_record(table, s->default_values);
@@ -6381,8 +6471,8 @@ bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
DBUG_ENTER("get_schema_constraints_record");
if (res)
@@ -6454,14 +6544,15 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
static bool store_trigger(THD *thd, Trigger *trigger,
- TABLE *table, LEX_STRING *db_name,
- LEX_STRING *table_name)
+ TABLE *table, const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
CHARSET_INFO *cs= system_charset_info;
- LEX_STRING sql_mode_rep;
+ LEX_CSTRING sql_mode_rep;
MYSQL_TIME timestamp;
char definer_holder[USER_HOST_BUFF_SIZE];
- LEX_STRING definer_buffer, trigger_stmt, trigger_body;
+ LEX_STRING definer_buffer;
+ LEX_CSTRING trigger_stmt, trigger_body;
definer_buffer.str= definer_holder;
trigger->get_trigger_info(&trigger_stmt, &trigger_body, &definer_buffer);
@@ -6510,8 +6601,8 @@ static bool store_trigger(THD *thd, Trigger *trigger,
static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
DBUG_ENTER("get_schema_triggers_record");
/*
@@ -6557,10 +6648,11 @@ ret:
}
-void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
- LEX_STRING *table_name, const char *key_name,
- uint key_len, const char *con_type, uint con_len,
- longlong idx)
+static void
+store_key_column_usage(TABLE *table, const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name, const char *key_name,
+ uint key_len, const char *con_type, uint con_len,
+ longlong idx)
{
CHARSET_INFO *cs= system_charset_info;
table->field[0]->store(STRING_WITH_LEN("def"), cs);
@@ -6577,8 +6669,8 @@ void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
static int get_schema_key_column_usage_record(THD *thd,
TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
DBUG_ENTER("get_schema_key_column_usage_record");
if (res)
@@ -6614,8 +6706,8 @@ static int get_schema_key_column_usage_record(THD *thd,
store_key_column_usage(table, db_name, table_name,
key_info->name,
strlen(key_info->name),
- key_part->field->field_name,
- strlen(key_part->field->field_name),
+ key_part->field->field_name.str,
+ key_part->field->field_name.length,
(longlong) f_idx);
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
@@ -6628,9 +6720,9 @@ static int get_schema_key_column_usage_record(THD *thd,
List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
while ((f_key_info= fkey_it++))
{
- LEX_STRING *f_info;
- LEX_STRING *r_info;
- List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
+ LEX_CSTRING *f_info;
+ LEX_CSTRING *r_info;
+ List_iterator_fast<LEX_CSTRING> it(f_key_info->foreign_fields),
it1(f_key_info->referenced_fields);
uint f_idx= 0;
while ((f_info= it++))
@@ -6666,10 +6758,10 @@ static int get_schema_key_column_usage_record(THD *thd,
#ifdef WITH_PARTITION_STORAGE_ENGINE
-static void collect_partition_expr(THD *thd, List<char> &field_list,
+static void collect_partition_expr(THD *thd, List<const char> &field_list,
String *str)
{
- List_iterator<char> part_it(field_list);
+ List_iterator<const char> part_it(field_list);
ulong no_fields= field_list.elements;
const char *field_str;
str->length(0);
@@ -6858,8 +6950,8 @@ get_partition_column_description(THD *thd,
static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name,
- LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
CHARSET_INFO *cs= system_charset_info;
char buff[61];
@@ -7153,7 +7245,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
/* SQL_MODE */
{
- LEX_STRING sql_mode;
+ LEX_CSTRING sql_mode;
sql_mode_string_representation(thd, et.sql_mode, &sql_mode);
sch_table->field[ISE_SQL_MODE]->
store(sql_mode.str, sql_mode.length, scs);
@@ -7175,7 +7267,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[ISE_INTERVAL_VALUE]->
store(show_str.ptr(), show_str.length(), scs);
- LEX_STRING *ival= &interval_type_to_name[et.interval];
+ LEX_CSTRING *ival= &interval_type_to_name[et.interval];
sch_table->field[ISE_INTERVAL_FIELD]->set_notnull();
sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs);
@@ -7409,7 +7501,8 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
static int
get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
- LEX_STRING *db_name, LEX_STRING *table_name)
+ const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name)
{
CHARSET_INFO *cs= system_charset_info;
LEX_CSTRING *s;
@@ -7587,6 +7680,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
for (; fields_info->field_name; fields_info++)
{
+ uint field_name_length= strlen(fields_info->field_name);
switch (fields_info->field_type) {
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_LONG:
@@ -7606,14 +7700,14 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
case MYSQL_TYPE_DATE:
if (!(item=new (mem_root)
Item_return_date_time(thd, fields_info->field_name,
- strlen(fields_info->field_name),
+ field_name_length,
fields_info->field_type)))
DBUG_RETURN(0);
break;
case MYSQL_TYPE_TIME:
if (!(item=new (mem_root)
Item_return_date_time(thd, fields_info->field_name,
- strlen(fields_info->field_name),
+ field_name_length,
fields_info->field_type)))
DBUG_RETURN(0);
break;
@@ -7621,7 +7715,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
case MYSQL_TYPE_DATETIME:
if (!(item=new (mem_root)
Item_return_date_time(thd, fields_info->field_name,
- strlen(fields_info->field_name),
+ field_name_length,
fields_info->field_type)))
DBUG_RETURN(0);
item->decimals= fields_info->field_length;
@@ -7654,8 +7748,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
item->max_length+= 1;
if (item->decimals > 0)
item->max_length+= 1;
- item->set_name(thd, fields_info->field_name,
- strlen(fields_info->field_name), cs);
+ item->set_name(thd, fields_info->field_name, field_name_length, cs);
break;
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
@@ -7678,7 +7771,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
DBUG_RETURN(0);
}
item->set_name(thd, fields_info->field_name,
- strlen(fields_info->field_name), cs);
+ field_name_length, cs);
break;
}
field_list.push_back(item, thd->mem_root);
@@ -7733,8 +7826,10 @@ static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
{
if (field_info->old_name)
{
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name)};
Item_field *field= new (thd->mem_root)
- Item_field(thd, context, NullS, NullS, field_info->field_name);
+ Item_field(thd, context, NullS, NullS, &field_name);
if (field)
{
field->set_name(thd, field_info->old_name,
@@ -7760,8 +7855,11 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
{
ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
String buffer(tmp,sizeof(tmp), system_charset_info);
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name) };
+
Item_field *field= new (thd->mem_root) Item_field(thd, context,
- NullS, NullS, field_info->field_name);
+ NullS, NullS, &field_name);
if (!field || add_item_to_list(thd, field))
return 1;
buffer.length(0);
@@ -7784,8 +7882,10 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
String buffer(tmp,sizeof(tmp), thd->charset());
LEX *lex= thd->lex;
Name_resolution_context *context= &lex->select_lex.context;
-
ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name) };
+
buffer.length(0);
buffer.append(field_info->old_name);
buffer.append(lex->select_lex.db);
@@ -7796,15 +7896,17 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
buffer.append(')');
}
Item_field *field= new (thd->mem_root) Item_field(thd, context,
- NullS, NullS, field_info->field_name);
+ NullS, NullS, &field_name);
if (add_item_to_list(thd, field))
return 1;
field->set_name(thd, buffer.ptr(), buffer.length(), system_charset_info);
if (thd->lex->verbose)
{
- field->set_name(thd, buffer.ptr(), buffer.length(), system_charset_info);
field_info= &schema_table->fields_info[3];
- field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name);
+ LEX_CSTRING field_name2= {field_info->field_name,
+ strlen(field_info->field_name) };
+ field= new (thd->mem_root) Item_field(thd, context, NullS, NullS,
+ &field_name2);
if (add_item_to_list(thd, field))
return 1;
field->set_name(thd, field_info->old_name, strlen(field_info->old_name),
@@ -7824,12 +7926,14 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
for (; *field_num >= 0; field_num++)
{
field_info= &schema_table->fields_info[*field_num];
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name)};
if (!thd->lex->verbose && (*field_num == 14 ||
*field_num == 18 ||
*field_num == 19))
continue;
Item_field *field= new (thd->mem_root) Item_field(thd, context,
- NullS, NullS, field_info->field_name);
+ NullS, NullS, &field_name);
if (field)
{
field->set_name(thd, field_info->old_name,
@@ -7853,8 +7957,10 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
for (; *field_num >= 0; field_num++)
{
field_info= &schema_table->fields_info[*field_num];
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name)};
Item_field *field= new (thd->mem_root) Item_field(thd, context,
- NullS, NullS, field_info->field_name);
+ NullS, NullS, &field_name);
if (field)
{
field->set_name(thd, field_info->old_name,
@@ -7878,8 +7984,10 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
for (; *field_num >= 0; field_num++)
{
field_info= &schema_table->fields_info[*field_num];
+ LEX_CSTRING field_name= {field_info->field_name,
+ strlen(field_info->field_name)};
Item_field *field= new (thd->mem_root) Item_field(thd, context,
- NullS, NullS, field_info->field_name);
+ NullS, NullS, &field_name);
if (field)
{
field->set_name(thd, field_info->old_name,
@@ -7993,7 +8101,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
int make_schema_select(THD *thd, SELECT_LEX *sel,
ST_SCHEMA_TABLE *schema_table)
{
- LEX_STRING db, table;
+ LEX_CSTRING db, table;
DBUG_ENTER("make_schema_select");
DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
/*
@@ -8011,7 +8119,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
if (schema_table->old_format(thd, schema_table))
DBUG_RETURN(1);
- if (!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
+ if (!sel->add_table_to_list(thd, new Table_ident(thd, &db, &table, 0),
0, 0, TL_READ, MDL_SHARED_READ))
DBUG_RETURN(1);
@@ -9389,8 +9497,8 @@ static bool show_create_trigger_impl(THD *thd, Trigger *trigger)
int ret_code;
Protocol *p= thd->protocol;
List<Item> fields;
- LEX_STRING trg_sql_mode_str, trg_body;
- LEX_STRING trg_sql_original_stmt;
+ LEX_CSTRING trg_sql_mode_str, trg_body;
+ LEX_CSTRING trg_sql_original_stmt;
LEX_STRING trg_definer;
CHARSET_INFO *trg_client_cs;
MEM_ROOT *mem_root= thd->mem_root;
@@ -9544,8 +9652,8 @@ TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
{
char trn_path_buff[FN_REFLEN];
LEX_STRING trn_path= { trn_path_buff, 0 };
- LEX_STRING db;
- LEX_STRING tbl_name;
+ LEX_CSTRING db;
+ LEX_CSTRING tbl_name;
TABLE_LIST *table;
build_trn_path(thd, trg_name, &trn_path);
@@ -9556,7 +9664,8 @@ TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
return NULL;
}
- if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
+ if (load_table_name_for_trigger(thd, trg_name, (LEX_CSTRING*) &trn_path,
+ &tbl_name))
return NULL;
/* We need to reset statement table list to be PS/SP friendly. */
@@ -9567,7 +9676,7 @@ TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
db.str= thd->strmake(db.str, db.length);
if (lower_case_table_names)
- db.length= my_casedn_str(files_charset_info, db.str);
+ db.length= my_casedn_str(files_charset_info, (char*) db.str);
tbl_name.str= thd->strmake(tbl_name.str, tbl_name.length);
diff --git a/sql/sql_show.h b/sql/sql_show.h
index e93b855450c..dc2fe9738fe 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -90,8 +90,8 @@ bool mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list,
List<Item> *field_list, String *buffer);
bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
void mysqld_show_create_db_get_fields(THD *thd, List<Item> *field_list);
-bool mysqld_show_create_db(THD *thd, LEX_STRING *db_name,
- LEX_STRING *orig_db_name,
+bool mysqld_show_create_db(THD *thd, LEX_CSTRING *db_name,
+ LEX_CSTRING *orig_db_name,
const DDL_options_st &options);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
@@ -103,8 +103,8 @@ bool mysqld_show_contributors(THD *thd);
bool mysqld_show_privileges(THD *thd);
char *make_backup_log_name(char *buff, const char *name, const char* log_ext);
uint calc_sum_of_all_status(STATUS_VAR *to);
-void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
- const LEX_STRING *definer_host);
+void append_definer(THD *thd, String *buffer, const LEX_CSTRING *definer_user,
+ const LEX_CSTRING *definer_host);
int add_status_vars(SHOW_VAR *list);
void remove_status_vars(SHOW_VAR *list);
void init_status_vars();
@@ -180,13 +180,13 @@ typedef struct st_lookup_field_values
Note that this value length may exceed @c NAME_LEN.
@sa wild_db_value
*/
- LEX_STRING db_value;
+ LEX_CSTRING db_value;
/**
Value of a TABLE_NAME clause.
Note that this value length may exceed @c NAME_LEN.
@sa wild_table_value
*/
- LEX_STRING table_value;
+ LEX_CSTRING table_value;
/**
True when @c db_value is a LIKE clause,
false when @c db_value is an '=' clause.
diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc
index 1b7edbee54a..6a57b8fc9ce 100644
--- a/sql/sql_signal.cc
+++ b/sql/sql_signal.cc
@@ -75,63 +75,6 @@ void Set_signal_information::clear()
memset(m_item, 0, sizeof(m_item));
}
-void
-Sql_cmd_common_signal::assign_defaults(Sql_condition *cond,
- bool set_level_code,
- Sql_condition::enum_warning_level level,
- int sqlcode)
-{
- if (set_level_code)
- {
- cond->m_level= level;
- cond->m_sql_errno= sqlcode;
- }
- if (! cond->get_message_text())
- cond->set_builtin_message_text(ER(sqlcode));
-}
-
-void Sql_cmd_common_signal::eval_defaults(THD *thd, Sql_condition *cond)
-{
- DBUG_ASSERT(cond);
-
- const char* sqlstate;
- bool set_defaults= (m_cond != 0);
-
- if (set_defaults)
- {
- /*
- SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
- */
- DBUG_ASSERT(m_cond->type == sp_condition_value::SQLSTATE);
- sqlstate= m_cond->sql_state;
- cond->set_sqlstate(sqlstate);
- }
- else
- sqlstate= cond->get_sqlstate();
-
- DBUG_ASSERT(sqlstate);
- /* SQLSTATE class "00": illegal, rejected in the parser. */
- DBUG_ASSERT((sqlstate[0] != '0') || (sqlstate[1] != '0'));
-
- if ((sqlstate[0] == '0') && (sqlstate[1] == '1'))
- {
- /* SQLSTATE class "01": warning. */
- assign_defaults(cond, set_defaults,
- Sql_condition::WARN_LEVEL_WARN, ER_SIGNAL_WARN);
- }
- else if ((sqlstate[0] == '0') && (sqlstate[1] == '2'))
- {
- /* SQLSTATE class "02": not found. */
- assign_defaults(cond, set_defaults,
- Sql_condition::WARN_LEVEL_ERROR, ER_SIGNAL_NOT_FOUND);
- }
- else
- {
- /* other SQLSTATE classes : error. */
- assign_defaults(cond, set_defaults,
- Sql_condition::WARN_LEVEL_ERROR, ER_SIGNAL_EXCEPTION);
- }
-}
static bool assign_fixed_string(MEM_ROOT *mem_root,
CHARSET_INFO *dst_cs,
@@ -402,7 +345,7 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond)
DBUG_ASSERT(thd->lex->query_tables == NULL);
- eval_defaults(thd, cond);
+ cond->assign_defaults(thd, m_cond);
if (eval_signal_informations(thd, cond))
DBUG_RETURN(result);
@@ -410,13 +353,7 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond)
DBUG_ASSERT((cond->m_level == Sql_condition::WARN_LEVEL_WARN) ||
(cond->m_level == Sql_condition::WARN_LEVEL_ERROR));
- Sql_condition *raised= NULL;
- raised= thd->raise_condition(cond->get_sql_errno(),
- cond->get_sqlstate(),
- cond->get_level(),
- cond->get_message_text());
- if (raised)
- raised->copy_opt_attributes(cond);
+ (void) thd->raise_condition(cond);
if (cond->m_level == Sql_condition::WARN_LEVEL_WARN)
{
@@ -430,7 +367,8 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond)
bool Sql_cmd_signal::execute(THD *thd)
{
bool result= TRUE;
- Sql_condition cond(thd->mem_root);
+ DBUG_ASSERT(m_cond);
+ Sql_condition cond(thd->mem_root, m_cond->get_user_condition_identity());
DBUG_ENTER("Sql_cmd_signal::execute");
@@ -484,11 +422,7 @@ bool Sql_cmd_resignal::execute(THD *thd)
DBUG_RETURN(result);
}
- Sql_condition signaled_err(thd->mem_root);
- signaled_err.set(signaled->sql_errno,
- signaled->sql_state,
- signaled->level,
- signaled->message);
+ Sql_condition signaled_err(thd->mem_root, *signaled, signaled->message);
if (m_cond)
{
@@ -500,13 +434,19 @@ bool Sql_cmd_resignal::execute(THD *thd)
/* Check if the old condition still exists. */
if (da->has_sql_condition(signaled->message, strlen(signaled->message)))
{
- /* Make room for the new RESIGNAL condition. */
- da->reserve_space(thd, 1);
+ /*
+ Make room for the new RESIGNAL condition and one for the stack trace
+ note.
+ */
+ da->reserve_space(thd, 2);
}
else
{
- /* Make room for old condition + the new RESIGNAL condition. */
- da->reserve_space(thd, 2);
+ /*
+ Make room for old condition + the new RESIGNAL condition + the stack
+ trace note.
+ */
+ da->reserve_space(thd, 3);
da->push_warning(thd, &signaled_err);
}
diff --git a/sql/sql_signal.h b/sql/sql_signal.h
index 2a508eed5bf..4d4601a5ec1 100644
--- a/sql/sql_signal.h
+++ b/sql/sql_signal.h
@@ -40,27 +40,6 @@ protected:
{}
/**
- Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
- default values of a condition.
- @param cond the condition to update.
- @param set_level_code true if 'level' and 'MYSQL_ERRNO' needs to be overwritten
- @param level the level to assign
- @param sqlcode the sql code to assign
- */
- static void assign_defaults(Sql_condition *cond,
- bool set_level_code,
- Sql_condition::enum_warning_level level,
- int sqlcode);
-
- /**
- Evaluate the condition items 'SQLSTATE', 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
- default values for this statement.
- @param thd the current thread.
- @param cond the condition to update.
- */
- void eval_defaults(THD *thd, Sql_condition *cond);
-
- /**
Evaluate each signal condition items for this statement.
@param thd the current thread.
@param cond the condition to update.
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index ad71f634265..3ec8fea29c6 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -471,9 +471,9 @@ protected:
/* Table for which statistical data is read / updated */
TABLE *table;
- TABLE_SHARE *table_share; /* Table share for 'table */
- LEX_STRING *db_name; /* Name of the database containing 'table' */
- LEX_STRING *table_name; /* Name of the table 'table' */
+ TABLE_SHARE *table_share; /* Table share for 'table */
+ LEX_CSTRING *db_name; /* Name of the database containing 'table' */
+ LEX_CSTRING *table_name; /* Name of the table 'table' */
void store_record_for_update()
{
@@ -528,7 +528,7 @@ public:
by the database name 'db' and the table name 'tab'.
*/
- Stat_table(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
+ Stat_table(TABLE *stat, LEX_CSTRING *db, LEX_CSTRING *tab)
:stat_table(stat), table_share(NULL)
{
common_init_stat_table();
@@ -553,7 +553,7 @@ public:
The method is called by the update_table_name_key_parts function.
*/
- virtual void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)= 0;
+ virtual void change_full_table_name(LEX_CSTRING *db, LEX_CSTRING *tab)= 0;
/**
@@ -703,7 +703,7 @@ public:
to store the new names in the record buffer used for updates.
*/
- bool update_table_name_key_parts(LEX_STRING *db, LEX_STRING *tab)
+ bool update_table_name_key_parts(LEX_CSTRING *db, LEX_CSTRING *tab)
{
store_record_for_update();
change_full_table_name(db, tab);
@@ -765,7 +765,7 @@ private:
table_name_field= stat_table->field[TABLE_STAT_TABLE_NAME];
}
- void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)
+ void change_full_table_name(LEX_CSTRING *db, LEX_CSTRING *tab)
{
db_name_field->store(db->str, db->length, system_charset_info);
table_name_field->store(tab->str, tab->length, system_charset_info);
@@ -795,7 +795,7 @@ public:
from the database 'db'.
*/
- Table_stat(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
+ Table_stat(TABLE *stat, LEX_CSTRING *db, LEX_CSTRING *tab)
:Stat_table(stat, db, tab)
{
common_init_table_stat();
@@ -909,7 +909,7 @@ private:
column_name_field= stat_table->field[COLUMN_STAT_COLUMN_NAME];
}
- void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)
+ void change_full_table_name(LEX_CSTRING *db, LEX_CSTRING *tab)
{
db_name_field->store(db->str, db->length, system_charset_info);
table_name_field->store(tab->str, tab->length, system_charset_info);
@@ -939,7 +939,7 @@ public:
from the database 'db'.
*/
- Column_stat(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
+ Column_stat(TABLE *stat, LEX_CSTRING *db, LEX_CSTRING *tab)
:Stat_table(stat, db, tab)
{
common_init_column_stat_table();
@@ -983,8 +983,7 @@ public:
void set_key_fields(Field *col)
{
set_full_table_name();
- const char *column_name= col->field_name;
- column_name_field->store(column_name, strlen(column_name),
+ column_name_field->store(col->field_name.str, col->field_name.length,
system_charset_info);
table_field= col;
}
@@ -1245,7 +1244,7 @@ private:
prefix_arity_field= stat_table->field[INDEX_STAT_PREFIX_ARITY];
}
- void change_full_table_name(LEX_STRING *db, LEX_STRING *tab)
+ void change_full_table_name(LEX_CSTRING *db, LEX_CSTRING *tab)
{
db_name_field->store(db->str, db->length, system_charset_info);
table_name_field->store(tab->str, tab->length, system_charset_info);
@@ -1277,7 +1276,7 @@ public:
from the database 'db'.
*/
- Index_stat(TABLE *stat, LEX_STRING *db, LEX_STRING *tab)
+ Index_stat(TABLE *stat, LEX_CSTRING *db, LEX_CSTRING *tab)
:Stat_table(stat, db, tab)
{
common_init_index_stat_table();
@@ -1320,7 +1319,7 @@ public:
void set_index_prefix_key_fields(KEY *index_info)
{
set_full_table_name();
- char *index_name= index_info->name;
+ const char *index_name= index_info->name;
index_name_field->store(index_name, strlen(index_name),
system_charset_info);
table_key_info= index_info;
@@ -1961,7 +1960,7 @@ void create_min_max_statistical_fields_for_table(TABLE *table)
for (uint i=0; i < 2; i++, record+= rec_buff_length)
{
- for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
+ for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *fld;
Field *table_field= *field_ptr;
@@ -2030,7 +2029,7 @@ void create_min_max_statistical_fields_for_table_share(THD *thd,
for (uint i=0; i < 2; i++, record+= rec_buff_length)
{
- for (Field **field_ptr= table_share->field; *field_ptr; field_ptr++)
+ for (Field **field_ptr= table_share->field; *field_ptr; field_ptr++)
{
Field *fld;
Field *table_field= *field_ptr;
@@ -2493,7 +2492,7 @@ bool Column_statistics_collected::add(ha_rows rowno)
set_not_null(COLUMN_STAT_MIN_VALUE);
if (max_value && column->update_max(max_value, rowno == nulls))
set_not_null(COLUMN_STAT_MAX_VALUE);
- if (count_distinct)
+ if (count_distinct)
err= count_distinct->add();
}
return err;
@@ -3283,7 +3282,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
The function is called when executing the statement DROP TABLE 'tab'.
*/
-int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab)
+int delete_statistics_for_table(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab)
{
int err;
enum_binlog_format save_binlog_format;
@@ -3521,8 +3520,8 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
The function is called when executing any statement that renames a table
*/
-int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab,
- LEX_STRING *new_db, LEX_STRING *new_tab)
+int rename_table_in_stat_tables(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab,
+ LEX_CSTRING *new_db, LEX_CSTRING *new_tab)
{
int err;
enum_binlog_format save_binlog_format;
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index f46583839d1..eb59b149753 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -94,12 +94,12 @@ int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *share,
bool is_safe);
int alloc_statistics_for_table(THD *thd, TABLE *table);
int update_statistics_for_table(THD *thd, TABLE *table);
-int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab);
+int delete_statistics_for_table(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab);
int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col);
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
bool ext_prefixes_only);
-int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab,
- LEX_STRING *new_db, LEX_STRING *new_tab);
+int rename_table_in_stat_tables(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab,
+ LEX_CSTRING *new_db, LEX_CSTRING *new_tab);
int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col,
const char *new_name);
void set_statistics_for_table(THD *thd, TABLE *table);
@@ -259,10 +259,10 @@ static inline
int rename_table_in_stat_tables(THD *thd, const char *db, const char *tab,
const char *new_db, const char *new_tab)
{
- LEX_STRING od= { const_cast<char*>(db), strlen(db) };
- LEX_STRING ot= { const_cast<char*>(tab), strlen(tab) };
- LEX_STRING nd= { const_cast<char*>(new_db), strlen(new_db) };
- LEX_STRING nt= { const_cast<char*>(new_tab), strlen(new_tab) };
+ LEX_CSTRING od= { db, strlen(db) };
+ LEX_CSTRING ot= { tab, strlen(tab) };
+ LEX_CSTRING nd= { new_db, strlen(new_db) };
+ LEX_CSTRING nt= { new_tab, strlen(new_tab) };
return rename_table_in_stat_tables(thd, &od, &ot, &nd, &nt);
}
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index c16b2ef9844..9a21c0a9144 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -130,6 +130,61 @@ bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs)
return FALSE;
}
+
+// Convert a number into its HEX representation
+bool String::set_hex(ulonglong num)
+{
+ char *n_end;
+ if (alloc(65) || !(n_end= longlong2str(num, Ptr, 16)))
+ return true;
+ length((uint32) (n_end - Ptr));
+ set_charset(&my_charset_latin1);
+ return false;
+}
+
+
+/**
+ Append a hex representation of the byte "value" into "to".
+ Note:
+ "to" is incremented for the caller by two bytes. It's passed by reference!
+ So it resembles a macros, hence capital letters in the name.
+*/
+static inline void APPEND_HEX(char *&to, uchar value)
+{
+ *to++= _dig_vec_upper[((uchar) value) >> 4];
+ *to++= _dig_vec_upper[((uchar) value) & 0x0F];
+}
+
+
+void String::qs_append_hex(const char *str, uint32 len)
+{
+ const char *str_end= str + len;
+ for (char *to= Ptr + str_length ; str < str_end; str++)
+ APPEND_HEX(to, (uchar) *str);
+ str_length+= len * 2;
+}
+
+
+// Convert a string to its HEX representation
+bool String::set_hex(const char *str, uint32 len)
+{
+ /*
+ Safety: cut the source string if "len" is too large.
+ Note, alloc() can allocate some more space than requested, due to:
+ - ALIGN_SIZE
+ - one extra byte for a null terminator
+ So cut the source string to 0x7FFFFFF0 rather than 0x7FFFFFFE.
+ */
+ set_if_smaller(len, 0x7FFFFFF0);
+ if (alloc(len * 2))
+ return true;
+ length(0);
+ qs_append_hex(str, len);
+ set_charset(&my_charset_latin1);
+ return false;
+}
+
+
bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
{
char buff[FLOATING_POINT_BUFFER];
@@ -968,8 +1023,7 @@ my_copy_with_hex_escaping(CHARSET_INFO *cs,
break; /* purecov: inspected */
*dst++= '\\';
*dst++= 'x';
- *dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
- *dst++= _dig_vec_upper[((unsigned char) *src) & 15];
+ APPEND_HEX(dst, (uchar) *src);
src++;
dstlen-= 4;
}
@@ -1154,8 +1208,7 @@ uint convert_to_printable(char *to, size_t to_len,
break;
*t++= '\\';
*t++= 'x';
- *t++= _dig_vec_upper[((unsigned char) *f) >> 4];
- *t++= _dig_vec_upper[((unsigned char) *f) & 0x0F];
+ APPEND_HEX(t, *f);
}
if (t_end - t >= 3) // '...'
dots= t;
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 9a9fff8522c..845ed4c9746 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -293,6 +293,9 @@ public:
bool set(ulonglong num, CHARSET_INFO *cs) { return set_int((longlong)num, true, cs); }
bool set_real(double num,uint decimals, CHARSET_INFO *cs);
+ bool set_hex(ulonglong num);
+ bool set_hex(const char *str, uint32 len);
+
/* Take over handling of buffer from some other object */
void reset(char *ptr_arg, uint32 length_arg, uint32 alloced_length_arg,
CHARSET_INFO *cs)
@@ -557,6 +560,10 @@ public:
memcpy(Ptr + str_length, data, data_len);
str_length += data_len;
}
+ void q_append(const LEX_CSTRING *ls)
+ {
+ q_append(ls->str, ls->length);
+ }
void write_at_position(int position, uint32 value)
{
@@ -568,6 +575,7 @@ public:
qs_append(str, (uint32)strlen(str));
}
void qs_append(const char *str, uint32 len);
+ void qs_append_hex(const char *str, uint32 len);
void qs_append(double d);
void qs_append(double *d);
inline void qs_append(const char c)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5c5f2d373c7..beac24ed1c4 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -54,7 +54,7 @@
#include "sql_show.h"
#include "transaction.h"
#include "sql_audit.h"
-
+#include "sql_sequence.h"
#ifdef __WIN__
#include <io.h>
@@ -65,7 +65,7 @@ const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
static char *make_unique_key_name(THD *thd, const char *field_name, KEY *start,
KEY *end);
-static void make_unique_constraint_name(THD *thd, LEX_STRING *name,
+static void make_unique_constraint_name(THD *thd, LEX_CSTRING *name,
List<Virtual_column_info> *vcol,
uint *nr);
static int copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
@@ -75,7 +75,6 @@ static int copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
Alter_info::enum_enable_or_disable keys_onoff,
Alter_table_ctx *alter_ctx);
-static bool prepare_blob_field(THD *thd, Column_definition *sql_field);
static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *,
uint *, handler *, KEY **, uint *, int);
static uint blob_length_by_type(enum_field_types type);
@@ -1085,7 +1084,7 @@ static bool deactivate_ddl_log_entry_no_lock(uint entry_no)
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
{
bool frm_action= FALSE;
- LEX_STRING handler_name;
+ LEX_CSTRING handler_name;
handler *file= NULL;
MEM_ROOT mem_root;
int error= TRUE;
@@ -1989,6 +1988,8 @@ int write_bin_log(THD *thd, bool clear_error,
thd Thread handle
tables List of tables to delete
if_exists If 1, don't give error if one table doesn't exists
+ drop_temporary 1 if DROP TEMPORARY
+ drop_seqeunce 1 if DROP SEQUENCE
NOTES
Will delete all tables that can be deleted and give a compact error
@@ -2005,8 +2006,8 @@ int write_bin_log(THD *thd, bool clear_error,
*/
-bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
- my_bool drop_temporary)
+bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
+ bool drop_temporary, bool drop_sequence)
{
bool error;
Drop_table_error_handler err_handler;
@@ -2026,8 +2027,8 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
{
for (table= tables; table; table= table->next_local)
{
- LEX_STRING db_name= { table->db, table->db_length };
- LEX_STRING table_name= { table->table_name, table->table_name_length };
+ LEX_CSTRING db_name= { table->db, table->db_length };
+ LEX_CSTRING table_name= { table->table_name, table->table_name_length };
if (table->open_type == OT_BASE_ONLY ||
!thd->find_temporary_table(table))
(void) delete_statistics_for_table(thd, &db_name, &table_name);
@@ -2083,7 +2084,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
/* mark for close and remove all cached entries */
thd->push_internal_handler(&err_handler);
error= mysql_rm_table_no_locks(thd, tables, if_exists, drop_temporary,
- false, false, false);
+ false, drop_sequence, false, false);
thd->pop_internal_handler();
if (error)
@@ -2172,11 +2173,13 @@ static uint32 comment_length(THD *thd, uint32 comment_pos,
int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
bool drop_temporary, bool drop_view,
+ bool drop_sequence,
bool dont_log_query,
bool dont_free_locks)
{
TABLE_LIST *table;
- char path[FN_REFLEN + 1], wrong_tables_buff[160], *alias= NULL;
+ char path[FN_REFLEN + 1], wrong_tables_buff[160];
+ const char *alias= NULL;
String wrong_tables(wrong_tables_buff, sizeof(wrong_tables_buff)-1,
system_charset_info);
uint path_length= 0, errors= 0;
@@ -2186,7 +2189,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0;
bool non_tmp_table_deleted= 0;
bool is_drop_tmp_if_exists_added= 0;
- bool was_view= 0;
+ bool was_view= 0, was_table= 0, is_sequence;
String built_query;
String built_trans_tmp_query, built_non_trans_tmp_query;
DBUG_ENTER("mysql_rm_table_no_locks");
@@ -2228,17 +2231,21 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
*/
if (!dont_log_query)
{
+ const char *object_to_drop= (drop_sequence) ? "SEQUENCE" : "TABLE";
+
if (!drop_temporary)
{
const char *comment_start;
uint32 comment_len;
built_query.set_charset(thd->charset());
+ built_query.append("DROP ");
+ built_query.append(object_to_drop);
+ built_query.append(' ');
if (if_exists)
- built_query.append("DROP TABLE IF EXISTS ");
- else
- built_query.append("DROP TABLE ");
+ built_query.append("IF EXISTS ");
+ /* Preserve comment in original query */
if ((comment_len= comment_length(thd, if_exists ? 17:9, &comment_start)))
{
built_query.append(comment_start, comment_len);
@@ -2246,28 +2253,24 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
}
}
+ built_trans_tmp_query.set_charset(system_charset_info);
+ built_trans_tmp_query.append("DROP TEMPORARY ");
+ built_trans_tmp_query.append(object_to_drop);
+ built_trans_tmp_query.append(' ');
if (thd->is_current_stmt_binlog_format_row() || if_exists)
{
is_drop_tmp_if_exists_added= true;
- built_trans_tmp_query.set_charset(system_charset_info);
- built_trans_tmp_query.append("DROP TEMPORARY TABLE IF EXISTS ");
- built_non_trans_tmp_query.set_charset(system_charset_info);
- built_non_trans_tmp_query.append("DROP TEMPORARY TABLE IF EXISTS ");
- }
- else
- {
- built_trans_tmp_query.set_charset(system_charset_info);
- built_trans_tmp_query.append("DROP TEMPORARY TABLE ");
- built_non_trans_tmp_query.set_charset(system_charset_info);
- built_non_trans_tmp_query.append("DROP TEMPORARY TABLE ");
+ built_trans_tmp_query.append("IF EXISTS ");
}
+ built_non_trans_tmp_query.set_charset(system_charset_info);
+ built_non_trans_tmp_query.copy(built_trans_tmp_query);
}
for (table= tables; table; table= table->next_local)
{
bool is_trans= 0;
bool table_creation_was_logged= 1;
- char *db=table->db;
+ const char *db= table->db;
size_t db_length= table->db_length;
handlerton *table_type= 0;
@@ -2285,7 +2288,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
thd->find_temporary_table(table) &&
table->mdl_request.ticket != NULL));
- if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table))
+ if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) ||
+ (drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE))
error= 1;
else
{
@@ -2393,26 +2397,31 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
error= 0;
if (drop_temporary ||
- (ha_table_exists(thd, db, alias, &table_type) == 0 && table_type == 0) ||
- (!drop_view && (was_view= (table_type == view_pseudo_hton))))
+ (ha_table_exists(thd, db, alias, &table_type, &is_sequence) == 0 &&
+ table_type == 0) ||
+ (!drop_view && (was_view= (table_type == view_pseudo_hton))) ||
+ (drop_sequence && !is_sequence))
{
/*
One of the following cases happened:
. "DROP TEMPORARY" but a temporary table was not found.
. "DROP" but table was not found
. "DROP TABLE" statement, but it's a view.
+ . "DROP SEQUENCE", but it's not a sequence
*/
+ was_table= drop_sequence && table_type;
if (if_exists)
{
char buff[FN_REFLEN];
+ int err= (drop_sequence ? ER_UNKNOWN_SEQUENCES :
+ ER_BAD_TABLE_ERROR);
String tbl_name(buff, sizeof(buff), system_charset_info);
tbl_name.length(0);
tbl_name.append(db);
tbl_name.append('.');
tbl_name.append(table->table_name);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_BAD_TABLE_ERROR,
- ER_THD(thd, ER_BAD_TABLE_ERROR),
+ err, ER_THD(thd, err),
tbl_name.c_ptr_safe());
}
else
@@ -2529,8 +2538,12 @@ err:
DBUG_ASSERT(errors);
if (errors == 1 && was_view)
my_error(ER_IT_IS_A_VIEW, MYF(0), wrong_tables.c_ptr_safe());
+ else if (errors == 1 && drop_sequence && was_table)
+ my_error(ER_NOT_SEQUENCE2, MYF(0), wrong_tables.c_ptr_safe());
else if (errors > 1 || !thd->is_error())
- my_error(ER_BAD_TABLE_ERROR, MYF(0), wrong_tables.c_ptr_safe());
+ my_error((drop_sequence ? ER_UNKNOWN_SEQUENCES :
+ ER_BAD_TABLE_ERROR),
+ MYF(0), wrong_tables.c_ptr_safe());
error= 1;
}
@@ -2829,206 +2842,98 @@ bool check_duplicates_in_interval(const char *set_or_name,
}
-/*
- Check TYPELIB (set or enum) max and total lengths
+bool Column_definition::prepare_stage2_blob(handler *file,
+ ulonglong table_flags,
+ uint field_flags)
+{
+ if (table_flags & HA_NO_BLOBS)
+ {
+ my_error(ER_TABLE_CANT_HANDLE_BLOB, MYF(0), file->table_type());
+ return true;
+ }
+ pack_flag= field_flags |
+ pack_length_to_packflag(pack_length - portable_sizeof_char_ptr);
+ if (charset->state & MY_CS_BINSORT)
+ pack_flag|= FIELDFLAG_BINARY;
+ length= 8; // Unireg field length
+ return false;
+}
- SYNOPSIS
- calculate_interval_lengths()
- cs charset+collation pair of the interval
- typelib list of values for the column
- max_length length of the longest item
- tot_length sum of the item lengths
- DESCRIPTION
- After this function call:
- - ENUM uses max_length
- - SET uses tot_length.
+bool Column_definition::prepare_stage2_typelib(const char *type_name,
+ uint field_flags,
+ uint *dup_val_count)
+{
+ pack_flag= pack_length_to_packflag(pack_length) | field_flags;
+ if (charset->state & MY_CS_BINSORT)
+ pack_flag|= FIELDFLAG_BINARY;
+ return check_duplicates_in_interval(type_name, field_name.str, interval,
+ charset, dup_val_count);
+}
- RETURN VALUES
- void
-*/
-void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
- uint32 *max_length, uint32 *tot_length)
+
+uint Column_definition::pack_flag_numeric(uint dec) const
+{
+ return (FIELDFLAG_NUMBER |
+ (flags & UNSIGNED_FLAG ? 0 : FIELDFLAG_DECIMAL) |
+ (flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0) |
+ (dec << FIELDFLAG_DEC_SHIFT));
+}
+
+
+bool Column_definition::prepare_stage2_varchar(ulonglong table_flags)
{
- const char **pos;
- uint *len;
- *max_length= *tot_length= 0;
- for (pos= interval->type_names, len= interval->type_lengths;
- *pos ; pos++, len++)
+#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
+ if (table_flags & HA_NO_VARCHAR)
{
- size_t length= cs->cset->numchars(cs, *pos, *pos + *len);
- *tot_length+= length;
- set_if_bigger(*max_length, (uint32)length);
+ /* convert VARCHAR to CHAR because handler is not yet up to date */
+ set_handler(&type_handler_var_string);
+ pack_length= type_handler()->calc_pack_length((uint) length);
+ if ((length / charset->mbmaxlen) > MAX_FIELD_CHARLENGTH)
+ {
+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
+ static_cast<ulong>(MAX_FIELD_CHARLENGTH));
+ return true;
+ }
}
+#endif
+ pack_flag= (charset->state & MY_CS_BINSORT) ? FIELDFLAG_BINARY : 0;
+ return false;
}
/*
- Prepare a create_table instance for packing
-
- SYNOPSIS
- prepare_create_field()
- sql_field field to prepare for packing
- blob_columns count for BLOBs
- table_flags table flags
+ Prepare a Column_definition instance for packing
+ Members such as pack_flag are valid after this call.
- DESCRIPTION
- This function prepares a Create_field instance.
- Fields such as pack_flag are valid after this call.
+ @param IN handler - storage engine handler,
+ or NULL if preparing for an SP variable
+ @param IN table_flags - table flags
- RETURN VALUES
- 0 ok
- 1 Error
+ @retval false - ok
+ @retval true - error (not supported type, bad definition, etc)
*/
-int prepare_create_field(Column_definition *sql_field,
- uint *blob_columns,
- ulonglong table_flags)
+bool Column_definition::prepare_stage2(handler *file,
+ ulonglong table_flags)
{
- uint dup_val_count;
- uint decimals= sql_field->decimals;
- DBUG_ENTER("prepare_create_field");
+ DBUG_ENTER("Column_definition::prepare_stage2");
/*
This code came from mysql_prepare_create_table.
Indent preserved to make patching easier
*/
- DBUG_ASSERT(sql_field->charset);
+ DBUG_ASSERT(charset);
- switch (sql_field->sql_type) {
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- sql_field->pack_flag=FIELDFLAG_BLOB |
- pack_length_to_packflag(sql_field->pack_length -
- portable_sizeof_char_ptr);
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->length=8; // Unireg field length
- (*blob_columns)++;
- break;
- case MYSQL_TYPE_GEOMETRY:
-#ifdef HAVE_SPATIAL
- if (!(table_flags & HA_CAN_GEOMETRY))
- {
- my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
- DBUG_RETURN(1);
- }
- sql_field->pack_flag=FIELDFLAG_GEOM |
- pack_length_to_packflag(sql_field->pack_length -
- portable_sizeof_char_ptr);
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->length=8; // Unireg field length
- (*blob_columns)++;
- break;
-#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- DBUG_RETURN(1);
-#endif /*HAVE_SPATIAL*/
- case MYSQL_TYPE_VARCHAR:
-#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
- if (table_flags & HA_NO_VARCHAR)
- {
- /* convert VARCHAR to CHAR because handler is not yet up to date */
- sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
- sql_field->pack_length= calc_pack_length(sql_field->sql_type,
- (uint) sql_field->length);
- if ((sql_field->length / sql_field->charset->mbmaxlen) >
- MAX_FIELD_CHARLENGTH)
- {
- my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
- static_cast<ulong>(MAX_FIELD_CHARLENGTH));
- DBUG_RETURN(1);
- }
- }
-#endif
- /* fall through */
- case MYSQL_TYPE_STRING:
- sql_field->pack_flag=0;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- break;
- case MYSQL_TYPE_ENUM:
- sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_INTERVAL;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- if (check_duplicates_in_interval("ENUM",sql_field->field_name,
- sql_field->interval,
- sql_field->charset, &dup_val_count))
- DBUG_RETURN(1);
- break;
- case MYSQL_TYPE_SET:
- sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_BITFIELD;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- if (check_duplicates_in_interval("SET",sql_field->field_name,
- sql_field->interval,
- sql_field->charset, &dup_val_count))
- DBUG_RETURN(1);
- /* Check that count of unique members is not more then 64 */
- if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8)
- {
- my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
- DBUG_RETURN(1);
- }
- break;
- case MYSQL_TYPE_DATE: // Rest of string types
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIME2:
- case MYSQL_TYPE_DATETIME2:
- case MYSQL_TYPE_NULL:
- sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
- break;
- case MYSQL_TYPE_BIT:
- /*
- We have sql_field->pack_flag already set here, see
- mysql_prepare_create_table().
- */
- break;
- case MYSQL_TYPE_NEWDECIMAL:
- sql_field->pack_flag=(FIELDFLAG_NUMBER |
- (sql_field->flags & UNSIGNED_FLAG ? 0 :
- FIELDFLAG_DECIMAL) |
- (sql_field->flags & ZEROFILL_FLAG ?
- FIELDFLAG_ZEROFILL : 0) |
- (decimals << FIELDFLAG_DEC_SHIFT));
- break;
- case MYSQL_TYPE_FLOAT:
- case MYSQL_TYPE_DOUBLE:
- /*
- User specified FLOAT() or DOUBLE() without precision. Change to
- FLOATING_POINT_DECIMALS to keep things compatible with earlier MariaDB
- versions.
- */
- if (decimals >= FLOATING_POINT_DECIMALS)
- decimals= FLOATING_POINT_DECIMALS;
- /* fall-trough */
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_TIMESTAMP2:
- /* fall-through */
- default:
- sql_field->pack_flag=(FIELDFLAG_NUMBER |
- (sql_field->flags & UNSIGNED_FLAG ? 0 :
- FIELDFLAG_DECIMAL) |
- (sql_field->flags & ZEROFILL_FLAG ?
- FIELDFLAG_ZEROFILL : 0) |
- f_settype((uint) sql_field->sql_type) |
- (decimals << FIELDFLAG_DEC_SHIFT));
- break;
- }
- if (!(sql_field->flags & NOT_NULL_FLAG) ||
- (sql_field->vcol_info)) /* Make virtual columns allow NULL values */
- sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
- if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
- sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
- DBUG_RETURN(0);
+ if (type_handler()->Column_definition_prepare_stage2(this, file, table_flags))
+ DBUG_RETURN(true);
+
+ if (!(flags & NOT_NULL_FLAG) ||
+ (vcol_info)) /* Make virtual columns allow NULL values */
+ pack_flag|= FIELDFLAG_MAYBE_NULL;
+ if (flags & NO_DEFAULT_VALUE_FLAG)
+ pack_flag|= FIELDFLAG_NO_DEFAULT;
+ DBUG_RETURN(false);
}
@@ -3045,7 +2950,7 @@ int prepare_create_field(Column_definition *sql_field,
cs Character set
*/
-CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
HA_CREATE_INFO *create_info)
{
CHARSET_INFO *cs= sql_field->charset;
@@ -3082,7 +2987,7 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
while ((column_definition= it++) != NULL)
{
- if (is_timestamp_type(column_definition->sql_type) || // TIMESTAMP
+ if (column_definition->is_timestamp_type() || // TIMESTAMP
column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
{
if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
@@ -3093,7 +2998,7 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
"DEFAULT CURRENT_TIMESTAMP ON UPDATE "
"CURRENT_TIMESTAMP",
- column_definition->field_name
+ column_definition->field_name.str
));
column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
}
@@ -3184,6 +3089,143 @@ static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
}
+bool Column_definition::prepare_stage1_typelib(THD *thd,
+ MEM_ROOT *mem_root,
+ handler *file,
+ ulonglong table_flags)
+{
+ /*
+ Pass the last parameter to prepare_interval_field() as follows:
+ - If we are preparing for an SP variable (file is NULL), we pass "false",
+ to force allocation and full copying of TYPELIB values on the given
+ mem_root, even if no character set conversion is needed. This is needed
+ because a life cycle of an SP variable is longer than the current query.
+
+ - If we are preparing for a CREATE TABLE, (file != NULL), we pass "true".
+ This will create the typelib in runtime memory - we will free the
+ occupied memory at the same time when we free this
+ sql_field -- at the end of execution.
+ Pass "true" as the last argument to reuse "interval_list"
+ values in "interval" in cases when no character conversion is needed,
+ to avoid extra copying.
+ */
+ if (prepare_interval_field(mem_root, file != NULL))
+ return true; // E.g. wrong values with commas: SET('a,b')
+ create_length_to_internal_length_typelib();
+
+ DBUG_ASSERT(file || !default_value); // SP variables have no default_value
+ if (default_value && default_value->expr->basic_const_item())
+ {
+ if ((charset != default_value->expr->collation.collation &&
+ prepare_stage1_convert_default(thd, mem_root, charset)) ||
+ prepare_stage1_check_typelib_default())
+ return true;
+ }
+ return false;
+}
+
+
+bool Column_definition::prepare_stage1_string(THD *thd,
+ MEM_ROOT *mem_root,
+ handler *file,
+ ulonglong table_flags)
+{
+ create_length_to_internal_length_string();
+ if (prepare_blob_field(thd))
+ return true;
+ DBUG_ASSERT(file || !default_value); // SP variables have no default_value
+ /*
+ Convert the default value from client character
+ set into the column character set if necessary.
+ We can only do this for constants as we have not yet run fix_fields.
+ */
+ if (default_value &&
+ default_value->expr->basic_const_item() &&
+ charset != default_value->expr->collation.collation)
+ {
+ if (prepare_stage1_convert_default(thd, mem_root, charset))
+ return true;
+ }
+ return false;
+}
+
+
+bool Column_definition::prepare_stage1_bit(THD *thd,
+ MEM_ROOT *mem_root,
+ handler *file,
+ ulonglong table_flags)
+{
+ pack_flag= FIELDFLAG_NUMBER;
+ if (!(table_flags & HA_CAN_BIT_FIELD))
+ pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
+ create_length_to_internal_length_bit();
+ return false;
+}
+
+
+bool Column_definition::prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ handler *file,
+ ulonglong table_flags)
+{
+ return type_handler()->Column_definition_prepare_stage1(thd, mem_root,
+ this, file,
+ table_flags);
+}
+
+
+bool Column_definition::prepare_stage1_convert_default(THD *thd,
+ MEM_ROOT *mem_root,
+ CHARSET_INFO *cs)
+{
+ DBUG_ASSERT(thd->mem_root == mem_root);
+ Item *item;
+ if (!(item= default_value->expr->safe_charset_converter(thd, cs)))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
+ return true; // Could not convert
+ }
+ /* Fix for prepare statement */
+ thd->change_item_tree(&default_value->expr, item);
+ return false;
+}
+
+
+bool Column_definition::prepare_stage1_check_typelib_default()
+{
+ StringBuffer<MAX_FIELD_WIDTH> str;
+ String *def= default_value->expr->val_str(&str);
+ bool not_found;
+ if (def == NULL) /* SQL "NULL" maps to NULL */
+ {
+ not_found= flags & NOT_NULL_FLAG;
+ }
+ else
+ {
+ not_found= false;
+ if (real_field_type() == MYSQL_TYPE_SET)
+ {
+ char *not_used;
+ uint not_used2;
+ find_set(interval, def->ptr(), def->length(),
+ charset, &not_used, &not_used2, &not_found);
+ }
+ else /* MYSQL_TYPE_ENUM */
+ {
+ def->length(charset->cset->lengthsp(charset,
+ def->ptr(), def->length()));
+ not_found= !find_type2(interval, def->ptr(), def->length(), charset);
+ }
+ }
+ if (not_found)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
+ return true;
+ }
+ return false;
+}
+
+
/*
Preparation for table creation
@@ -3218,7 +3260,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{
const char *key_name;
Create_field *sql_field,*dup_field;
- uint field,null_fields,blob_columns,max_key_length;
+ uint field,null_fields,max_key_length;
ulong record_offset= 0;
KEY *key_info;
KEY_PART_INFO *key_part_info;
@@ -3231,7 +3273,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
bool tmp_table= create_table_mode == C_ALTER_TABLE;
DBUG_ENTER("mysql_prepare_create_table");
- LEX_STRING* connect_string = &create_info->connect_string;
+ LEX_CSTRING* connect_string = &create_info->connect_string;
if (connect_string->length != 0 &&
connect_string->length > CONNECT_STRING_MAXLEN &&
(system_charset_info->cset->charpos(system_charset_info,
@@ -3247,14 +3289,28 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
select_field_pos= alter_info->create_list.elements - select_field_count;
- null_fields=blob_columns=0;
+ null_fields= 0;
create_info->varchar= 0;
max_key_length= file->max_key_length();
- for (field_no=0; (sql_field=it++) ; field_no++)
+ /* Handle creation of sequences */
+ if (create_info->sequence)
{
- CHARSET_INFO *save_cs;
+ if (!(file->ha_table_flags() & HA_CAN_TABLES_WITHOUT_ROLLBACK))
+ {
+ my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), file->engine_name()->str,
+ "SEQUENCE");
+ DBUG_RETURN(TRUE);
+ }
+
+ /* The user specified fields: check that structure is ok */
+ if (check_sequence_fields(thd->lex, &alter_info->create_list))
+ DBUG_RETURN(TRUE);
+ }
+ select_field_pos= alter_info->create_list.elements - select_field_count;
+ for (field_no=0; (sql_field=it++) ; field_no++)
+ {
/*
Initialize length from its original value (number of characters),
which was set in the parser. This is necessary if we're
@@ -3262,175 +3318,25 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
*/
sql_field->length= sql_field->char_length;
/* Set field charset. */
- save_cs= sql_field->charset= get_sql_field_charset(sql_field, create_info);
+ sql_field->charset= get_sql_field_charset(sql_field, create_info);
if ((sql_field->flags & BINCMP_FLAG) &&
- !(sql_field->charset= find_bin_collation(sql_field->charset)))
- DBUG_RETURN(TRUE);
-
- if (sql_field->sql_type == MYSQL_TYPE_SET ||
- sql_field->sql_type == MYSQL_TYPE_ENUM)
- {
- uint32 dummy;
- CHARSET_INFO *cs= sql_field->charset;
- TYPELIB *interval= sql_field->interval;
-
- /*
- Create typelib from interval_list, and if necessary
- convert strings from client character set to the
- column character set.
- */
- if (!interval)
- {
- /*
- Create the typelib in runtime memory - we will free the
- occupied memory at the same time when we free this
- sql_field -- at the end of execution.
- */
- interval= sql_field->interval= typelib(thd->mem_root,
- sql_field->interval_list);
- List_iterator<String> int_it(sql_field->interval_list);
- String conv, *tmp;
- char comma_buf[5]; /* 5 bytes for 'filename' charset */
- DBUG_ASSERT(sizeof(comma_buf) >= cs->mbmaxlen);
- int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
- (uchar*) comma_buf +
- sizeof(comma_buf));
- DBUG_ASSERT(comma_length > 0);
- for (uint i= 0; (tmp= int_it++); i++)
- {
- size_t lengthsp;
- if (String::needs_conversion(tmp->length(), tmp->charset(),
- cs, &dummy))
- {
- uint cnv_errs;
- conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
- interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
- conv.length());
- interval->type_lengths[i]= conv.length();
- }
-
- // Strip trailing spaces.
- lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
- interval->type_lengths[i]);
- interval->type_lengths[i]= lengthsp;
- ((uchar *)interval->type_names[i])[lengthsp]= '\0';
- if (sql_field->sql_type == MYSQL_TYPE_SET)
- {
- if (cs->coll->instr(cs, interval->type_names[i],
- interval->type_lengths[i],
- comma_buf, comma_length, NULL, 0))
- {
- ErrConvString err(tmp->ptr(), tmp->length(), cs);
- my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", err.ptr());
- DBUG_RETURN(TRUE);
- }
- }
- }
- sql_field->interval_list.empty(); // Don't need interval_list anymore
- }
-
- if (sql_field->sql_type == MYSQL_TYPE_SET)
- {
- uint32 field_length;
- calculate_interval_lengths(cs, interval, &dummy, &field_length);
- sql_field->length= field_length + (interval->count - 1);
- }
- else /* MYSQL_TYPE_ENUM */
- {
- uint32 field_length;
- DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
- calculate_interval_lengths(cs, interval, &field_length, &dummy);
- sql_field->length= field_length;
- }
- set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
- }
-
- if (sql_field->sql_type == MYSQL_TYPE_BIT)
- {
- sql_field->pack_flag= FIELDFLAG_NUMBER;
- if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
- total_uneven_bit_length+= sql_field->length & 7;
- else
- sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
- }
-
- sql_field->create_length_to_internal_length();
- if (prepare_blob_field(thd, sql_field))
- DBUG_RETURN(TRUE);
-
- /*
- Convert the default value from client character
- set into the column character set if necessary.
- We can only do this for constants as we have not yet run fix_fields.
- */
- if (sql_field->default_value &&
- sql_field->default_value->expr->basic_const_item() &&
- save_cs != sql_field->default_value->expr->collation.collation &&
- (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
- sql_field->sql_type == MYSQL_TYPE_STRING ||
- sql_field->sql_type == MYSQL_TYPE_SET ||
- sql_field->sql_type == MYSQL_TYPE_TINY_BLOB ||
- sql_field->sql_type == MYSQL_TYPE_MEDIUM_BLOB ||
- sql_field->sql_type == MYSQL_TYPE_LONG_BLOB ||
- sql_field->sql_type == MYSQL_TYPE_BLOB ||
- sql_field->sql_type == MYSQL_TYPE_ENUM))
- {
- Item *item;
- if (!(item= sql_field->default_value->expr->
- safe_charset_converter(thd, save_cs)))
- {
- /* Could not convert */
- my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
- DBUG_RETURN(TRUE);
- }
- /* Fix for prepare statement */
- thd->change_item_tree(&sql_field->default_value->expr, item);
- }
+ !(sql_field->charset= find_bin_collation(sql_field->charset)))
+ DBUG_RETURN(true);
- if (sql_field->default_value &&
- sql_field->default_value->expr->basic_const_item() &&
- (sql_field->sql_type == MYSQL_TYPE_SET ||
- sql_field->sql_type == MYSQL_TYPE_ENUM))
- {
- StringBuffer<MAX_FIELD_WIDTH> str;
- String *def= sql_field->default_value->expr->val_str(&str);
- bool not_found;
- if (def == NULL) /* SQL "NULL" maps to NULL */
- {
- not_found= sql_field->flags & NOT_NULL_FLAG;
- }
- else
- {
- not_found= false;
- if (sql_field->sql_type == MYSQL_TYPE_SET)
- {
- char *not_used;
- uint not_used2;
- find_set(sql_field->interval, def->ptr(), def->length(),
- sql_field->charset, &not_used, &not_used2, &not_found);
- }
- else /* MYSQL_TYPE_ENUM */
- {
- def->length(sql_field->charset->cset->lengthsp(sql_field->charset,
- def->ptr(), def->length()));
- not_found= !find_type2(sql_field->interval, def->ptr(),
- def->length(), sql_field->charset);
- }
- }
+ if (sql_field->prepare_stage1(thd, thd->mem_root,
+ file, file->ha_table_flags()))
+ DBUG_RETURN(true);
- if (not_found)
- {
- my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
- DBUG_RETURN(TRUE);
- }
- }
+ if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
+ file->ha_table_flags() & HA_CAN_BIT_FIELD)
+ total_uneven_bit_length+= sql_field->length & 7;
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
- if (check_column_name(sql_field->field_name))
+ if (check_column_name(sql_field->field_name.str))
{
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
+ my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
@@ -3438,8 +3344,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
{
if (my_strcasecmp(system_charset_info,
- sql_field->field_name,
- dup_field->field_name) == 0)
+ sql_field->field_name.str,
+ dup_field->field_name.str) == 0)
{
/*
If this was a CREATE ... SELECT statement, accept a field
@@ -3447,7 +3353,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
*/
if (field_no < select_field_pos || dup_no >= select_field_pos)
{
- my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
+ my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
else
@@ -3458,34 +3364,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
If we are replacing a BIT field, revert the increment
of total_uneven_bit_length that was done above.
*/
- if (sql_field->sql_type == MYSQL_TYPE_BIT &&
+ if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
file->ha_table_flags() & HA_CAN_BIT_FIELD)
total_uneven_bit_length-= sql_field->length & 7;
- sql_field->default_value= dup_field->default_value;
- sql_field->sql_type= dup_field->sql_type;
-
- /*
- If we are replacing a field with a BIT field, we need
- to initialize pack_flag. Note that we do not need to
- increment total_uneven_bit_length here as this dup_field
- has already been processed.
- */
- if (sql_field->sql_type == MYSQL_TYPE_BIT)
- {
- sql_field->pack_flag= FIELDFLAG_NUMBER;
- if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD))
- sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
- }
-
- sql_field->charset= (dup_field->charset ?
- dup_field->charset :
- create_info->default_table_charset);
- sql_field->length= dup_field->char_length;
- sql_field->pack_length= dup_field->pack_length;
- sql_field->key_length= dup_field->key_length;
- sql_field->decimals= dup_field->decimals;
- sql_field->unireg_check= dup_field->unireg_check;
/*
We're making one field from two, the result field will have
dup_field->flags as flags. If we've incremented null_fields
@@ -3493,10 +3375,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
*/
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields--;
- sql_field->flags= dup_field->flags;
- sql_field->create_length_to_internal_length();
- sql_field->interval= dup_field->interval;
- sql_field->vcol_info= dup_field->vcol_info;
+
+ if (sql_field->redefine_stage1(dup_field, file, create_info))
+ DBUG_RETURN(true);
+
it2.remove(); // Remove first (create) definition
select_field_pos--;
break;
@@ -3505,7 +3387,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
/* Don't pack rows in old tables if the user has requested this */
if ((sql_field->flags & BLOB_FLAG) ||
- (sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
+ (sql_field->real_field_type() == MYSQL_TYPE_VARCHAR &&
create_info->row_type != ROW_TYPE_FIXED))
(*db_options)|= HA_OPTION_PACK_RECORD;
it2.rewind();
@@ -3520,10 +3402,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{
DBUG_ASSERT(sql_field->charset != 0);
- if (prepare_create_field(sql_field, &blob_columns,
- file->ha_table_flags()))
+ if (sql_field->prepare_stage2(file, file->ha_table_flags()))
DBUG_RETURN(TRUE);
- if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
+ if (sql_field->real_field_type() == MYSQL_TYPE_VARCHAR)
create_info->varchar= TRUE;
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
@@ -3563,12 +3444,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE);
}
- if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
- {
- my_error(ER_TABLE_CANT_HANDLE_BLOB, MYF(0), file->table_type());
- DBUG_RETURN(TRUE);
- }
-
/*
CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows
inserted in the created table depends on the order of the rows fetched
@@ -3804,7 +3679,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
while ((sql_field=it++) &&
my_strcasecmp(system_charset_info,
column->field_name.str,
- sql_field->field_name))
+ sql_field->field_name.str))
field++;
if (!sql_field)
{
@@ -3823,8 +3698,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
cols2.rewind();
if (key->type == Key::FULLTEXT)
{
- if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
- sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
+ if ((sql_field->real_field_type() != MYSQL_TYPE_STRING &&
+ sql_field->real_field_type() != MYSQL_TYPE_VARCHAR &&
!f_is_blob(sql_field->pack_flag)) ||
sql_field->charset == &my_charset_bin ||
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
@@ -3902,7 +3777,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (sql_field->vcol_info->flags & VCOL_NOT_STRICTLY_DETERMINISTIC)
{
/* use check_expression() to report an error */
- check_expression(sql_field->vcol_info, sql_field->field_name,
+ check_expression(sql_field->vcol_info, &sql_field->field_name,
VCOL_GENERATED_STORED);
DBUG_ASSERT(thd->is_error());
DBUG_RETURN(TRUE);
@@ -3950,7 +3825,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (f_is_blob(sql_field->pack_flag))
{
key_part_length= MY_MIN(column->length,
- blob_length_by_type(sql_field->sql_type)
+ blob_length_by_type(sql_field->real_field_type())
* sql_field->charset->mbmaxlen);
if (key_part_length > max_key_length ||
key_part_length > file->max_key_part_length())
@@ -3980,7 +3855,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
// is prefix length bigger than field length?
(column->length > key_part_length ||
// can the field have a partial key?
- !Field::type_can_have_key_part (sql_field->sql_type) ||
+ !sql_field->type_handler()->type_can_have_key_part() ||
// a packed field can't be used in a partial key
f_is_packed(sql_field->pack_flag) ||
// does the storage engine allow prefixed search?
@@ -4024,12 +3899,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
!((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
(key_part_length >= KEY_DEFAULT_PACK_LENGTH &&
- (sql_field->sql_type == MYSQL_TYPE_STRING ||
- sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
+ (sql_field->real_field_type() == MYSQL_TYPE_STRING ||
+ sql_field->real_field_type() == MYSQL_TYPE_VARCHAR ||
sql_field->pack_flag & FIELDFLAG_BLOB)))
{
if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
- sql_field->sql_type == MYSQL_TYPE_VARCHAR)
+ sql_field->real_field_type() == MYSQL_TYPE_VARCHAR)
key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
else
key_info->flags|= HA_PACK_KEY;
@@ -4056,7 +3931,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
primary_key=1;
}
else if (!(key_name= key->name.str))
- key_name=make_unique_key_name(thd, sql_field->field_name,
+ key_name=make_unique_key_name(thd, sql_field->field_name.str,
*key_info_buffer, key_info);
if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
{
@@ -4081,7 +3956,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
if (validate_comment_length(thd, &key->key_create_info.comment,
- INDEX_COMMENT_MAXLEN, ER_TOO_LONG_INDEX_COMMENT,
+ INDEX_COMMENT_MAXLEN,
+ ER_TOO_LONG_INDEX_COMMENT,
key_info->name))
DBUG_RETURN(TRUE);
@@ -4129,7 +4005,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (!sql_field->default_value &&
!sql_field->has_default_function() &&
(sql_field->flags & NOT_NULL_FLAG) &&
- !is_timestamp_type(sql_field->sql_type))
+ !sql_field->is_timestamp_type())
{
sql_field->flags|= NO_DEFAULT_VALUE_FLAG;
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
@@ -4137,7 +4013,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
!sql_field->default_value && !sql_field->vcol_info &&
- is_timestamp_type(sql_field->sql_type) &&
+ sql_field->is_timestamp_type() &&
(sql_field->flags & NOT_NULL_FLAG) &&
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
{
@@ -4155,7 +4031,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
'column_name TIMESTAMP DEFAULT 0'.
*/
- my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
}
@@ -4195,7 +4071,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str);
DBUG_RETURN(TRUE);
}
- if (check_expression(check, check->name.str, VCOL_CHECK_TABLE))
+ if (check_expression(check, &check->name, VCOL_CHECK_TABLE))
DBUG_RETURN(TRUE);
}
}
@@ -4238,7 +4114,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
@retval true Error found
@retval false On Success
*/
-bool validate_comment_length(THD *thd, LEX_STRING *comment, size_t max_len,
+bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
uint err_code, const char *name)
{
DBUG_ENTER("validate_comment_length");
@@ -4274,7 +4150,8 @@ bool validate_comment_length(THD *thd, LEX_STRING *comment, size_t max_len,
*/
static void set_table_default_charset(THD *thd,
- HA_CREATE_INFO *create_info, char *db)
+ HA_CREATE_INFO *create_info,
+ const char *db)
{
/*
If the table character set was not given explicitly,
@@ -4297,7 +4174,6 @@ static void set_table_default_charset(THD *thd,
SYNOPSIS
prepare_blob_field()
- sql_field Field to check
RETURN
0 ok
@@ -4305,45 +4181,42 @@ static void set_table_default_charset(THD *thd,
In this case the error is given
*/
-static bool prepare_blob_field(THD *thd, Column_definition *sql_field)
+bool Column_definition::prepare_blob_field(THD *thd)
{
- DBUG_ENTER("prepare_blob_field");
+ DBUG_ENTER("Column_definition::prepare_blob_field");
- if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
- !(sql_field->flags & BLOB_FLAG))
+ if (length > MAX_FIELD_VARCHARLENGTH && !(flags & BLOB_FLAG))
{
/* Convert long VARCHAR columns to TEXT or BLOB */
char warn_buff[MYSQL_ERRMSG_SIZE];
if (thd->is_strict_mode())
{
- my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
- static_cast<ulong>(MAX_FIELD_VARCHARLENGTH /
- sql_field->charset->mbmaxlen));
+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
+ static_cast<ulong>(MAX_FIELD_VARCHARLENGTH / charset->mbmaxlen));
DBUG_RETURN(1);
}
- sql_field->sql_type= MYSQL_TYPE_BLOB;
- sql_field->flags|= BLOB_FLAG;
+ set_handler(&type_handler_blob);
+ flags|= BLOB_FLAG;
my_snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT),
- sql_field->field_name,
- (sql_field->charset == &my_charset_bin) ? "VARBINARY" :
- "VARCHAR",
- (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
+ field_name.str,
+ (charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
+ (charset == &my_charset_bin) ? "BLOB" : "TEXT");
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
warn_buff);
}
- if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
+ if ((flags & BLOB_FLAG) && length)
{
- if (sql_field->sql_type == FIELD_TYPE_BLOB ||
- sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
- sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB)
+ if (real_field_type() == FIELD_TYPE_BLOB ||
+ real_field_type() == FIELD_TYPE_TINY_BLOB ||
+ real_field_type() == FIELD_TYPE_MEDIUM_BLOB)
{
/* The user has given a length to the blob column */
- sql_field->sql_type= get_blob_type_from_length(sql_field->length);
- sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
+ set_handler(Type_handler::blob_type_handler(length));
+ pack_length= type_handler()->calc_pack_length(0);
}
- sql_field->length= 0;
+ length= 0;
}
DBUG_RETURN(0);
}
@@ -4356,47 +4229,18 @@ static bool prepare_blob_field(THD *thd, Column_definition *sql_field)
SYNOPSIS
sp_prepare_create_field()
- thd Thread object
- sql_field Field to prepare
+ thd Thread object
+ mem_root Memory root to allocate components on (e.g. interval)
DESCRIPTION
Prepares the field structures for field creation.
*/
-void sp_prepare_create_field(THD *thd, Column_definition *sql_field)
+bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
{
- if (sql_field->sql_type == MYSQL_TYPE_SET ||
- sql_field->sql_type == MYSQL_TYPE_ENUM)
- {
- uint32 field_length, dummy;
- if (sql_field->sql_type == MYSQL_TYPE_SET)
- {
- calculate_interval_lengths(sql_field->charset,
- sql_field->interval, &dummy,
- &field_length);
- sql_field->length= field_length +
- (sql_field->interval->count - 1);
- }
- else /* MYSQL_TYPE_ENUM */
- {
- calculate_interval_lengths(sql_field->charset,
- sql_field->interval,
- &field_length, &dummy);
- sql_field->length= field_length;
- }
- set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
- }
-
- if (sql_field->sql_type == MYSQL_TYPE_BIT)
- {
- sql_field->pack_flag= FIELDFLAG_NUMBER |
- FIELDFLAG_TREAT_BIT_AS_CHAR;
- }
- sql_field->create_length_to_internal_length();
- DBUG_ASSERT(sql_field->default_value == 0);
- /* Can't go wrong as sql_field->def is not defined */
- (void) prepare_blob_field(thd, sql_field);
+ return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY) ||
+ prepare_stage2(NULL, HA_CAN_GEOMETRY);
}
@@ -4473,15 +4317,16 @@ handler *mysql_create_frm_image(THD *thd,
{
if (part_elem->part_comment)
{
- LEX_STRING comment= {
- part_elem->part_comment, strlen(part_elem->part_comment)
+ LEX_CSTRING comment= { part_elem->part_comment,
+ strlen(part_elem->part_comment)
};
if (validate_comment_length(thd, &comment,
TABLE_PARTITION_COMMENT_MAXLEN,
ER_TOO_LONG_TABLE_PARTITION_COMMENT,
part_elem->partition_name))
DBUG_RETURN(NULL);
- part_elem->part_comment[comment.length]= '\0';
+ /* cut comment length. Safe to do in all cases */
+ ((char*)part_elem->part_comment)[comment.length]= '\0';
}
if (part_elem->subpartitions.elements)
{
@@ -4491,7 +4336,7 @@ handler *mysql_create_frm_image(THD *thd,
{
if (subpart_elem->part_comment)
{
- LEX_STRING comment= {
+ LEX_CSTRING comment= {
subpart_elem->part_comment, strlen(subpart_elem->part_comment)
};
if (validate_comment_length(thd, &comment,
@@ -4499,7 +4344,8 @@ handler *mysql_create_frm_image(THD *thd,
ER_TOO_LONG_TABLE_PARTITION_COMMENT,
subpart_elem->partition_name))
DBUG_RETURN(NULL);
- subpart_elem->part_comment[comment.length]= '\0';
+ /* cut comment length. Safe to do in all cases */
+ ((char*)subpart_elem->part_comment)[comment.length]= '\0';
}
}
}
@@ -4796,7 +4642,7 @@ int create_table_impl(THD *thd,
*/
(void) trans_rollback_stmt(thd);
/* Remove normal table without logging. Keep tables locked */
- if (mysql_rm_table_no_locks(thd, &table_list, 0, 0, 0, 1, 1))
+ if (mysql_rm_table_no_locks(thd, &table_list, 0, 0, 0, 0, 1, 1))
goto err;
/*
@@ -4943,7 +4789,7 @@ int create_table_impl(THD *thd,
}
}
#endif
-
+
error= 0;
err:
THD_STAGE_INFO(thd, stage_after_create);
@@ -4966,10 +4812,11 @@ warn:
*/
int mysql_create_table_no_lock(THD *thd,
- const char *db, const char *table_name,
- Table_specification_st *create_info,
- Alter_info *alter_info, bool *is_trans,
- int create_table_mode)
+ const char *db, const char *table_name,
+ Table_specification_st *create_info,
+ Alter_info *alter_info, bool *is_trans,
+ int create_table_mode,
+ TABLE_LIST *table_list)
{
KEY *not_used_1;
uint not_used_2;
@@ -4988,7 +4835,7 @@ int mysql_create_table_no_lock(THD *thd,
// Check if we hit FN_REFLEN bytes along with file extension.
if (length+reg_ext_length > FN_REFLEN)
{
- my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(path)-1, path);
+ my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), (int) sizeof(path)-1, path);
return true;
}
}
@@ -4998,6 +4845,17 @@ int mysql_create_table_no_lock(THD *thd,
alter_info, create_table_mode,
is_trans, &not_used_1, &not_used_2, &frm);
my_free(const_cast<uchar*>(frm.str));
+
+ if (!res && create_info->sequence)
+ {
+ /* Set create_info.table if temporary table */
+ if (create_info->tmp_table())
+ table_list->table= create_info->table;
+ else
+ table_list->table= 0;
+ res= sequence_insert(thd, thd->lex, table_list);
+ }
+
return res;
}
@@ -5059,7 +4917,8 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
promote_first_timestamp_column(&alter_info->create_list);
if (mysql_create_table_no_lock(thd, db, table_name, create_info, alter_info,
- &is_trans, create_table_mode) > 0)
+ &is_trans, create_table_mode,
+ create_table) > 0)
{
result= 1;
goto err;
@@ -5166,7 +5025,7 @@ make_unique_key_name(THD *thd, const char *field_name,KEY *start,KEY *end)
Make an unique name for constraints without a name
*/
-static void make_unique_constraint_name(THD *thd, LEX_STRING *name,
+static void make_unique_constraint_name(THD *thd, LEX_CSTRING *name,
List<Virtual_column_info> *vcol,
uint *nr)
{
@@ -5252,7 +5111,7 @@ mysql_rename_table(handlerton *base, const char *old_db,
// Check if we hit FN_REFLEN bytes along with file extension.
if (length+reg_ext_length > FN_REFLEN)
{
- my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(to)-1, to);
+ my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), (int) sizeof(to)-1, to);
DBUG_RETURN(TRUE);
}
@@ -5449,7 +5308,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
res= ((create_res=
mysql_create_table_no_lock(thd, table->db, table->table_name,
&local_create_info, &local_alter_info,
- &is_trans, C_ORDINARY_CREATE)) > 0);
+ &is_trans, C_ORDINARY_CREATE,
+ table)) > 0);
/* Remember to log if we deleted something */
do_logging= thd->log_current_statement;
if (res)
@@ -5690,7 +5550,7 @@ int mysql_discard_or_import_tablespace(THD *thd,
table_list->mdl_request.set_type(MDL_EXCLUSIVE);
table_list->lock_type= TL_WRITE;
/* Do not open views. */
- table_list->required_type= FRMTYPE_TABLE;
+ table_list->required_type= TABLE_TYPE_NORMAL;
if (open_and_lock_tables(thd, table_list, FALSE, 0,
&alter_prelocking_strategy))
@@ -5716,9 +5576,8 @@ int mysql_discard_or_import_tablespace(THD *thd,
error= trans_commit_stmt(thd);
if (trans_commit_implicit(thd))
error=1;
- if (error)
- goto err;
- error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ if (!error)
+ error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
err:
thd->tablespace_op=FALSE;
@@ -5787,7 +5646,7 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
while ((sql_field=it++))
{
- if (!sql_field->create_if_not_exists || sql_field->change)
+ if (!sql_field->create_if_not_exists || sql_field->change.str)
continue;
/*
If there is a field with the same name in the table already,
@@ -5796,7 +5655,7 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
- sql_field->field_name, (*f_ptr)->field_name) == 0)
+ sql_field->field_name.str, (*f_ptr)->field_name.str) == 0)
goto drop_create_field;
}
{
@@ -5809,7 +5668,7 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
while ((chk_field= chk_it++) && chk_field != sql_field)
{
if (my_strcasecmp(system_charset_info,
- sql_field->field_name, chk_field->field_name) == 0)
+ sql_field->field_name.str, chk_field->field_name.str) == 0)
goto drop_create_field;
}
}
@@ -5817,7 +5676,7 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
drop_create_field:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DUP_FIELDNAME, ER_THD(thd, ER_DUP_FIELDNAME),
- sql_field->field_name);
+ sql_field->field_name.str);
it.remove();
if (alter_info->create_list.is_empty())
{
@@ -5836,7 +5695,7 @@ drop_create_field:
while ((sql_field=it++))
{
- if (!sql_field->create_if_not_exists || !sql_field->change)
+ if (!sql_field->create_if_not_exists || !sql_field->change.str)
continue;
/*
If there is NO field with the same name in the table already,
@@ -5845,7 +5704,7 @@ drop_create_field:
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
- sql_field->change, (*f_ptr)->field_name) == 0)
+ sql_field->change.str, (*f_ptr)->field_name.str) == 0)
{
break;
}
@@ -5855,7 +5714,7 @@ drop_create_field:
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_BAD_FIELD_ERROR,
ER_THD(thd, ER_BAD_FIELD_ERROR),
- sql_field->change, table->s->table_name.str);
+ sql_field->change.str, table->s->table_name.str);
it.remove();
if (alter_info->create_list.is_empty())
{
@@ -5887,7 +5746,7 @@ drop_create_field:
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
- drop->name, (*f_ptr)->field_name) == 0)
+ drop->name, (*f_ptr)->field_name.str) == 0)
{
remove_drop= FALSE;
break;
@@ -6118,8 +5977,8 @@ remove_key:
if ((alter_info->flags & Alter_info::ALTER_DROP_PARTITION) &&
thd->lex->if_exists())
{
- List_iterator<char> names_it(alter_info->partition_names);
- char *name;
+ List_iterator<const char> names_it(alter_info->partition_names);
+ const char *name;
while ((name= names_it++))
{
@@ -6471,13 +6330,13 @@ static bool fill_alter_inplace_info(THD *thd,
}
/* Check if field was renamed */
- if (my_strcasecmp(system_charset_info, field->field_name,
- new_field->field_name))
+ if (my_strcasecmp(system_charset_info, field->field_name.str,
+ new_field->field_name.str))
{
field->flags|= FIELD_IS_RENAMED;
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_NAME;
rename_column_in_stat_tables(thd, table, field,
- new_field->field_name);
+ new_field->field_name.str);
}
/* Check that NULL behavior is same for old and new fields */
@@ -6922,14 +6781,14 @@ bool mysql_compare_tables(TABLE *table,
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
create_info->row_type == ROW_TYPE_PAGE ||
(tmp_new_field->flags & BLOB_FLAG) ||
- (tmp_new_field->sql_type == MYSQL_TYPE_VARCHAR &&
+ (tmp_new_field->real_field_type() == MYSQL_TYPE_VARCHAR &&
create_info->row_type != ROW_TYPE_FIXED))
create_info->table_options|= HA_OPTION_PACK_RECORD;
/* Check if field was renamed */
if (my_strcasecmp(system_charset_info,
- field->field_name,
- tmp_new_field->field_name))
+ field->field_name.str,
+ tmp_new_field->field_name.str))
DBUG_RETURN(false);
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
@@ -7472,7 +7331,7 @@ blob_length_by_type(enum_field_types type)
case MYSQL_TYPE_MEDIUM_BLOB:
return 16777215;
case MYSQL_TYPE_LONG_BLOB:
- return 4294967295U;
+ return (uint) UINT_MAX32;
default:
DBUG_ASSERT(0); // we should never go here
return 0;
@@ -7591,6 +7450,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
if (!(used_fields & HA_CREATE_USED_CONNECTION))
create_info->connect_string= table->s->connect_string;
+ if (!(used_fields & HA_CREATE_USED_SEQUENCE))
+ create_info->sequence= table->s->table_type == TABLE_TYPE_SEQUENCE;
+
restore_record(table, s->default_values); // Empty record for DEFAULT
if ((create_info->fields_option_struct= (ha_field_option_struct**)
@@ -7615,7 +7477,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
while ((drop=drop_it++))
{
if (drop->type == Alter_drop::COLUMN &&
- !my_strcasecmp(system_charset_info,field->field_name, drop->name))
+ !my_strcasecmp(system_charset_info,field->field_name.str,
+ drop->name))
{
/* Reset auto_increment value if it was dropped */
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
@@ -7638,8 +7501,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
def_it.rewind();
while ((def=def_it++))
{
- if (def->change &&
- !my_strcasecmp(system_charset_info,field->field_name, def->change))
+ if (def->change.str &&
+ !my_strcasecmp(system_charset_info,field->field_name.str,
+ def->change.str))
break;
}
if (def)
@@ -7656,7 +7520,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0));
goto err;
}
- if (!def->after)
+ if (!def->after.str)
{
/*
If this ALTER TABLE doesn't have an AFTER clause for the modified
@@ -7680,7 +7544,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
Alter_column *alter;
while ((alter=alter_it++))
{
- if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
+ if (!my_strcasecmp(system_charset_info,field->field_name.str,
+ alter->name))
break;
}
if (alter)
@@ -7696,9 +7561,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
def_it.rewind();
while ((def=def_it++)) // Add new columns
{
- if (def->change && ! def->field)
+ if (def->change.str && ! def->field)
{
- my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change,
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change.str,
table->s->table_name.str);
goto err;
}
@@ -7709,10 +7574,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
flag to allow ALTER TABLE only if the table to be altered is empty.
*/
- if ((def->sql_type == MYSQL_TYPE_DATE ||
- def->sql_type == MYSQL_TYPE_NEWDATE ||
- def->sql_type == MYSQL_TYPE_DATETIME ||
- def->sql_type == MYSQL_TYPE_DATETIME2) &&
+ if ((def->real_field_type() == MYSQL_TYPE_DATE ||
+ def->real_field_type() == MYSQL_TYPE_NEWDATE ||
+ def->real_field_type() == MYSQL_TYPE_DATETIME ||
+ def->real_field_type() == MYSQL_TYPE_DATETIME2) &&
!alter_ctx->datetime_field &&
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
@@ -7720,12 +7585,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_ctx->datetime_field= def;
alter_ctx->error_if_not_empty= TRUE;
}
- if (!def->after)
+ if (!def->after.str)
new_create_list.push_back(def, thd->mem_root);
else
{
Create_field *find;
- if (def->change)
+ if (def->change.str)
{
find_it.rewind();
/*
@@ -7748,19 +7613,21 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
}
- if (def->after == first_keyword)
+ if (def->after.str == first_keyword)
new_create_list.push_front(def, thd->mem_root);
else
{
find_it.rewind();
while ((find=find_it++))
{
- if (!my_strcasecmp(system_charset_info, def->after, find->field_name))
+ if (!my_strcasecmp(system_charset_info, def->after.str,
+ find->field_name.str))
break;
}
if (!find)
{
- my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after.str,
+ table->s->table_name.str);
goto err;
}
find_it.after(def); // Put column after this
@@ -7788,7 +7655,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
{
- char *key_name= key_info->name;
+ const char *key_name= key_info->name;
Alter_drop *drop;
drop_it.rewind();
while ((drop=drop_it++))
@@ -7825,21 +7692,21 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{
if (!key_part->field)
continue; // Wrong field (from UNIREG)
- const char *key_part_name=key_part->field->field_name;
+ const char *key_part_name=key_part->field->field_name.str;
Create_field *cfield;
uint key_part_length;
field_it.rewind();
while ((cfield=field_it++))
{
- if (cfield->change)
+ if (cfield->change.str)
{
if (!my_strcasecmp(system_charset_info, key_part_name,
- cfield->change))
+ cfield->change.str))
break;
}
else if (!my_strcasecmp(system_charset_info,
- key_part_name, cfield->field_name))
+ key_part_name, cfield->field_name.str))
break;
}
if (!cfield)
@@ -7872,22 +7739,22 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
- data type maximum length is 255.
- key_part_length is 1016 (=254*4, where 4 is mbmaxlen)
*/
- if (!Field::type_can_have_key_part(cfield->field->type()) ||
- !Field::type_can_have_key_part(cfield->sql_type) ||
+ if (!cfield->field->type_handler()->type_can_have_key_part() ||
+ !cfield->type_handler()->type_can_have_key_part() ||
/* spatial keys can't have sub-key length */
(key_info->flags & HA_SPATIAL) ||
(cfield->field->field_length == key_part_length &&
!f_is_blob(key_part->key_type)) ||
- (cfield->length && (((cfield->sql_type >= MYSQL_TYPE_TINY_BLOB &&
- cfield->sql_type <= MYSQL_TYPE_BLOB) ?
- blob_length_by_type(cfield->sql_type) :
- cfield->length) <
+ (cfield->length &&
+ (((cfield->real_field_type() >= MYSQL_TYPE_TINY_BLOB &&
+ cfield->real_field_type() <= MYSQL_TYPE_BLOB) ?
+ blob_length_by_type(cfield->real_field_type()) :
+ cfield->length) <
key_part_length / key_part->field->charset()->mbmaxlen)))
key_part_length= 0; // Use whole field
}
key_part_length /= key_part->field->charset()->mbmaxlen;
- key_parts.push_back(new Key_part_spec(cfield->field_name,
- strlen(cfield->field_name),
+ key_parts.push_back(new Key_part_spec(&cfield->field_name,
key_part_length),
thd->mem_root);
}
@@ -7905,8 +7772,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
KEY_CREATE_INFO key_create_info;
Key *key;
enum Key::Keytype key_type;
+ LEX_CSTRING tmp_name;
bzero((char*) &key_create_info, sizeof(key_create_info));
-
key_create_info.algorithm= key_info->algorithm;
if (key_info->flags & HA_USES_BLOCK_SIZE)
key_create_info.block_size= key_info->block_size;
@@ -7935,10 +7802,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
else
key_type= Key::MULTIPLE;
- key= new Key(key_type, key_name, strlen(key_name),
- &key_create_info,
+ tmp_name.str= key_name;
+ tmp_name.length= strlen(key_name);
+ key= new Key(key_type, &tmp_name, &key_create_info,
MY_TEST(key_info->flags & HA_GENERATED_KEY),
- key_parts, key_info->option_list, DDL_options());
+ &key_parts, key_info->option_list, DDL_options());
new_key_list.push_back(key, thd->mem_root);
}
}
@@ -8063,7 +7931,7 @@ static Create_field *get_field_by_old_name(Alter_info *alter_info,
{
if (new_field->field &&
(my_strcasecmp(system_charset_info,
- new_field->field->field_name,
+ new_field->field->field_name.str,
old_name) == 0))
break;
}
@@ -8103,11 +7971,11 @@ enum fk_column_change_type
static enum fk_column_change_type
fk_check_column_changes(THD *thd, Alter_info *alter_info,
- List<LEX_STRING> &fk_columns,
+ List<LEX_CSTRING> &fk_columns,
const char **bad_column_name)
{
- List_iterator_fast<LEX_STRING> column_it(fk_columns);
- LEX_STRING *column;
+ List_iterator_fast<LEX_CSTRING> column_it(fk_columns);
+ LEX_CSTRING *column;
*bad_column_name= NULL;
@@ -8119,8 +7987,8 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info,
{
Field *old_field= new_field->field;
- if (my_strcasecmp(system_charset_info, old_field->field_name,
- new_field->field_name))
+ if (my_strcasecmp(system_charset_info, old_field->field_name.str,
+ new_field->field_name.str))
{
/*
Copy algorithm doesn't support proper renaming of columns in
@@ -8284,7 +8152,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
case FK_COLUMN_DROPPED:
{
StringBuffer<NAME_LEN*2+2> buff(system_charset_info);
- LEX_STRING *db= f_key->foreign_db, *tbl= f_key->foreign_table;
+ LEX_CSTRING *db= f_key->foreign_db, *tbl= f_key->foreign_table;
append_identifier(thd, &buff, db->str, db->length);
buff.append('.');
@@ -8486,11 +8354,11 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(true);
close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_RENAME, NULL);
- LEX_STRING old_db_name= { alter_ctx->db, strlen(alter_ctx->db) };
- LEX_STRING old_table_name=
+ LEX_CSTRING old_db_name= { alter_ctx->db, strlen(alter_ctx->db) };
+ LEX_CSTRING old_table_name=
{ alter_ctx->table_name, strlen(alter_ctx->table_name) };
- LEX_STRING new_db_name= { alter_ctx->new_db, strlen(alter_ctx->new_db) };
- LEX_STRING new_table_name=
+ LEX_CSTRING new_db_name= { alter_ctx->new_db, strlen(alter_ctx->new_db) };
+ LEX_CSTRING new_table_name=
{ alter_ctx->new_alias, strlen(alter_ctx->new_alias) };
(void) rename_table_in_stat_tables(thd, &old_db_name, &old_table_name,
&new_db_name, &new_table_name);
@@ -8578,7 +8446,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
based on information about the table changes from fill_alter_inplace_info().
*/
-bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
+bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
Alter_info *alter_info,
@@ -8629,7 +8497,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Note that RENAME TABLE the only ALTER clause which is supported for views
has been already processed.
*/
- table_list->required_type= FRMTYPE_TABLE;
+ table_list->required_type= TABLE_TYPE_NORMAL;
Alter_table_prelocking_strategy alter_prelocking_strategy;
@@ -8736,7 +8604,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Table maybe does not exist, but we got an exclusive lock
on the name, now we can safely try to find out for sure.
*/
- if (ha_table_exists(thd, alter_ctx.new_db, alter_ctx.new_name, 0))
+ if (ha_table_exists(thd, alter_ctx.new_db, alter_ctx.new_name))
{
/* Table will be closed in do_command() */
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
@@ -9472,7 +9340,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
char backup_name[32];
my_snprintf(backup_name, sizeof(backup_name), "%s2-%lx-%lx", tmp_file_prefix,
- current_pid, thd->thread_id);
+ current_pid, (long) thd->thread_id);
if (lower_case_table_names)
my_casedn_str(files_charset_info, backup_name);
if (mysql_rename_table(old_db_type, alter_ctx.db, alter_ctx.table_name,
@@ -9592,7 +9460,7 @@ err_new_table_cleanup:
{
const char *f_val= 0;
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
- switch (alter_ctx.datetime_field->sql_type)
+ switch (alter_ctx.datetime_field->real_field_type())
{
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_NEWDATE:
@@ -9612,7 +9480,7 @@ err_new_table_cleanup:
thd->abort_on_warning= true;
make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
f_val, strlength(f_val), t_type,
- alter_ctx.datetime_field->field_name);
+ alter_ctx.datetime_field->field_name.str);
thd->abort_on_warning= save_abort_on_warning;
}
@@ -9732,6 +9600,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
thd->abort_on_warning= !ignore && thd->is_strict_mode();
from->file->info(HA_STATUS_VARIABLE);
+ to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE);
to->file->ha_start_bulk_insert(from->file->stats.records,
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
@@ -10088,7 +9957,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
table->next_global= NULL;
table->lock_type= TL_READ;
/* Allow to open real tables only. */
- table->required_type= FRMTYPE_TABLE;
+ table->required_type= TABLE_TYPE_NORMAL;
if (thd->open_temporary_tables(table) ||
open_and_lock_tables(thd, table, FALSE, 0))
@@ -10274,7 +10143,7 @@ bool check_engine(THD *thd, const char *db_name,
if (no_substitution)
{
const char *engine_name= ha_resolve_storage_engine_name(req_engine);
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), engine_name, engine_name);
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), engine_name);
DBUG_RETURN(TRUE);
}
*new_engine= enf_engine;
diff --git a/sql/sql_table.h b/sql/sql_table.h
index 5abb25d1ea5..2e080462deb 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -196,7 +196,7 @@ int mysql_create_table_no_lock(THD *thd, const char *db,
const char *table_name,
Table_specification_st *create_info,
Alter_info *alter_info, bool *is_trans,
- int create_table_mode);
+ int create_table_mode, TABLE_LIST *table);
handler *mysql_create_frm_image(THD *thd,
const char *db, const char *table_name,
@@ -217,7 +217,7 @@ bool mysql_prepare_alter_table(THD *thd, TABLE *table,
Alter_table_ctx *alter_ctx);
bool mysql_trans_prepare_alter_copy_data(THD *thd);
bool mysql_trans_commit_alter_copy_data(THD *thd);
-bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
+bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
Alter_info *alter_info,
@@ -239,10 +239,11 @@ bool mysql_restore_table(THD* thd, TABLE_LIST* table_list);
bool mysql_checksum_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
-bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
- my_bool drop_temporary);
+bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
+ bool drop_temporary, bool drop_sequence);
int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
bool drop_temporary, bool drop_view,
+ bool drop_sequence,
bool log_query, bool dont_free_locks);
bool log_drop_table(THD *thd, const char *db_name, size_t db_name_length,
const char *table_name, size_t table_name_length,
@@ -252,10 +253,7 @@ bool quick_rm_table(THD *thd, handlerton *base, const char *db,
const char *table_path=0);
void close_cached_table(THD *thd, TABLE *table);
void sp_prepare_create_field(THD *thd, Column_definition *sql_field);
-int prepare_create_field(Column_definition *sql_field,
- uint *blob_columns,
- ulonglong table_flags);
-CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
+CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
HA_CREATE_INFO *create_info);
bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags);
int write_bin_log(THD *thd, bool clear_error,
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index e70872af6c5..33a82883f8f 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -135,7 +135,8 @@ void TEST_filesort(SORT_FIELD *sortorder,uint s_length)
out.append(*sortorder->field->table_name);
out.append('.');
}
- out.append(sortorder->field->field_name ? sortorder->field->field_name:
+ out.append(sortorder->field->field_name.str ?
+ sortorder->field->field_name.str :
"tmp_table_column");
}
else
@@ -236,11 +237,11 @@ static void print_keyuse(KEYUSE *keyuse)
keyuse->val->print(&str, QT_ORDINARY);
str.append('\0');
if (keyuse->is_for_hash_join())
- fieldname= keyuse->table->field[keyuse->keypart]->field_name;
+ fieldname= keyuse->table->field[keyuse->keypart]->field_name.str;
else if (keyuse->keypart == FT_KEYPART)
fieldname= "FT_KEYPART";
else
- fieldname= key_info->key_part[keyuse->keypart].field->field_name;
+ fieldname= key_info->key_part[keyuse->keypart].field->field_name.str;
ll2str(keyuse->used_tables, buf2, 16, 0);
fprintf(DBUG_FILE, "KEYUSE: %s.%s=%s optimize: %u used_tables: %s "
"ref_table_rows: %lu keypart_map: %0lx\n",
@@ -385,10 +386,10 @@ void print_sjm(SJ_MATERIALIZATION_INFO *sjm)
/*
Debugging help: force List<...>::elem function not be removed as unused.
*/
-Item* (List<Item>:: *dbug_list_item_elem_ptr)(int)= &List<Item>::elem;
-Item_equal* (List<Item_equal>:: *dbug_list_item_equal_elem_ptr)(int)=
+Item* (List<Item>:: *dbug_list_item_elem_ptr)(uint)= &List<Item>::elem;
+Item_equal* (List<Item_equal>:: *dbug_list_item_equal_elem_ptr)(uint)=
&List<Item_equal>::elem;
-TABLE_LIST* (List<TABLE_LIST>:: *dbug_list_table_list_elem_ptr)(int) =
+TABLE_LIST* (List<TABLE_LIST>:: *dbug_list_table_list_elem_ptr)(uint) =
&List<TABLE_LIST>::elem;
#endif
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index cad4bae03e8..c8ec1fc7f6a 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -40,27 +40,27 @@
See also interval_type, interval_names
*/
-LEX_STRING interval_type_to_name[INTERVAL_LAST] = {
- { C_STRING_WITH_LEN("YEAR")},
- { C_STRING_WITH_LEN("QUARTER")},
- { C_STRING_WITH_LEN("MONTH")},
- { C_STRING_WITH_LEN("WEEK")},
- { C_STRING_WITH_LEN("DAY")},
- { C_STRING_WITH_LEN("HOUR")},
- { C_STRING_WITH_LEN("MINUTE")},
- { C_STRING_WITH_LEN("SECOND")},
- { C_STRING_WITH_LEN("MICROSECOND")},
- { C_STRING_WITH_LEN("YEAR_MONTH")},
- { C_STRING_WITH_LEN("DAY_HOUR")},
- { C_STRING_WITH_LEN("DAY_MINUTE")},
- { C_STRING_WITH_LEN("DAY_SECOND")},
- { C_STRING_WITH_LEN("HOUR_MINUTE")},
- { C_STRING_WITH_LEN("HOUR_SECOND")},
- { C_STRING_WITH_LEN("MINUTE_SECOND")},
- { C_STRING_WITH_LEN("DAY_MICROSECOND")},
- { C_STRING_WITH_LEN("HOUR_MICROSECOND")},
- { C_STRING_WITH_LEN("MINUTE_MICROSECOND")},
- { C_STRING_WITH_LEN("SECOND_MICROSECOND")}
+LEX_CSTRING interval_type_to_name[INTERVAL_LAST] = {
+ { STRING_WITH_LEN("YEAR")},
+ { STRING_WITH_LEN("QUARTER")},
+ { STRING_WITH_LEN("MONTH")},
+ { STRING_WITH_LEN("WEEK")},
+ { STRING_WITH_LEN("DAY")},
+ { STRING_WITH_LEN("HOUR")},
+ { STRING_WITH_LEN("MINUTE")},
+ { STRING_WITH_LEN("SECOND")},
+ { STRING_WITH_LEN("MICROSECOND")},
+ { STRING_WITH_LEN("YEAR_MONTH")},
+ { STRING_WITH_LEN("DAY_HOUR")},
+ { STRING_WITH_LEN("DAY_MINUTE")},
+ { STRING_WITH_LEN("DAY_SECOND")},
+ { STRING_WITH_LEN("HOUR_MINUTE")},
+ { STRING_WITH_LEN("HOUR_SECOND")},
+ { STRING_WITH_LEN("MINUTE_SECOND")},
+ { STRING_WITH_LEN("DAY_MICROSECOND")},
+ { STRING_WITH_LEN("HOUR_MICROSECOND")},
+ { STRING_WITH_LEN("MINUTE_MICROSECOND")},
+ { STRING_WITH_LEN("SECOND_MICROSECOND")}
};
/* Calc weekday from daynr */
diff --git a/sql/sql_time.h b/sql/sql_time.h
index e0cab5cfa66..03e38c158f6 100644
--- a/sql/sql_time.h
+++ b/sql/sql_time.h
@@ -203,7 +203,7 @@ extern DATE_TIME_FORMAT global_date_format;
extern DATE_TIME_FORMAT global_datetime_format;
extern DATE_TIME_FORMAT global_time_format;
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
-extern LEX_STRING interval_type_to_name[];
+extern LEX_CSTRING interval_type_to_name[];
static inline bool
non_zero_hhmmssuu(const MYSQL_TIME *ltime)
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index ca9b1431785..291d55d61a2 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -34,8 +34,9 @@
#include "sp_cache.h" // sp_invalidate_cache
#include <mysys_err.h>
-LEX_STRING *make_lex_string(LEX_STRING *lex_str, const char* str, uint length,
- MEM_ROOT *mem_root)
+LEX_CSTRING *make_lex_string(LEX_CSTRING *lex_str,
+ const char* str, uint length,
+ MEM_ROOT *mem_root)
{
if (!(lex_str->str= strmake_root(mem_root, str, length)))
return 0;
@@ -56,9 +57,9 @@ public:
static Trigger_creation_ctx *create(THD *thd,
const char *db_name,
const char *table_name,
- const LEX_STRING *client_cs_name,
- const LEX_STRING *connection_cl_name,
- const LEX_STRING *db_cl_name);
+ const LEX_CSTRING *client_cs_name,
+ const LEX_CSTRING *connection_cl_name,
+ const LEX_CSTRING *db_cl_name);
Trigger_creation_ctx(CHARSET_INFO *client_cs,
CHARSET_INFO *connection_cl,
@@ -92,9 +93,9 @@ Trigger_creation_ctx *
Trigger_creation_ctx::create(THD *thd,
const char *db_name,
const char *table_name,
- const LEX_STRING *client_cs_name,
- const LEX_STRING *connection_cl_name,
- const LEX_STRING *db_cl_name)
+ const LEX_CSTRING *client_cs_name,
+ const LEX_CSTRING *connection_cl_name,
+ const LEX_CSTRING *db_cl_name)
{
CHARSET_INFO *client_cs;
CHARSET_INFO *connection_cl;
@@ -162,7 +163,7 @@ Trigger_creation_ctx::create(THD *thd,
/*************************************************************************/
-static const LEX_STRING triggers_file_type=
+static const LEX_CSTRING triggers_file_type=
{ C_STRING_WITH_LEN("TRIGGERS") };
const char * const TRG_EXT= ".TRG";
@@ -176,37 +177,37 @@ const char * const TRG_EXT= ".TRG";
static File_option triggers_file_parameters[]=
{
{
- { C_STRING_WITH_LEN("triggers") },
+ { STRING_WITH_LEN("triggers") },
my_offsetof(class Table_triggers_list, definitions_list),
FILE_OPTIONS_STRLIST
},
{
- { C_STRING_WITH_LEN("sql_modes") },
+ { STRING_WITH_LEN("sql_modes") },
my_offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
},
{
- { C_STRING_WITH_LEN("definers") },
+ { STRING_WITH_LEN("definers") },
my_offsetof(class Table_triggers_list, definers_list),
FILE_OPTIONS_STRLIST
},
{
- { C_STRING_WITH_LEN("client_cs_names") },
+ { STRING_WITH_LEN("client_cs_names") },
my_offsetof(class Table_triggers_list, client_cs_names),
FILE_OPTIONS_STRLIST
},
{
- { C_STRING_WITH_LEN("connection_cl_names") },
+ { STRING_WITH_LEN("connection_cl_names") },
my_offsetof(class Table_triggers_list, connection_cl_names),
FILE_OPTIONS_STRLIST
},
{
- { C_STRING_WITH_LEN("db_cl_names") },
+ { STRING_WITH_LEN("db_cl_names") },
my_offsetof(class Table_triggers_list, db_cl_names),
FILE_OPTIONS_STRLIST
},
{
- { C_STRING_WITH_LEN("created") },
+ { STRING_WITH_LEN("created") },
my_offsetof(class Table_triggers_list, create_times),
FILE_OPTIONS_ULLLIST
},
@@ -215,7 +216,7 @@ static File_option triggers_file_parameters[]=
File_option sql_modes_parameters=
{
- { C_STRING_WITH_LEN("sql_modes") },
+ { STRING_WITH_LEN("sql_modes") },
my_offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
};
@@ -238,18 +239,18 @@ static const int TRG_NUM_REQUIRED_PARAMETERS= 7;
struct st_trigname
{
- LEX_STRING trigger_table;
+ LEX_CSTRING trigger_table;
};
-static const LEX_STRING trigname_file_type=
- { C_STRING_WITH_LEN("TRIGGERNAME") };
+static const LEX_CSTRING trigname_file_type=
+ { STRING_WITH_LEN("TRIGGERNAME") };
const char * const TRN_EXT= ".TRN";
static File_option trigname_file_parameters[]=
{
{
- { C_STRING_WITH_LEN("trigger_table")},
+ { STRING_WITH_LEN("trigger_table")},
offsetof(struct st_trigname, trigger_table),
FILE_OPTIONS_ESTRING
},
@@ -260,9 +261,9 @@ static File_option trigname_file_parameters[]=
class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
{
private:
- char *path;
+ const char *path;
public:
- Handle_old_incorrect_sql_modes_hook(char *file_path)
+ Handle_old_incorrect_sql_modes_hook(const char *file_path)
:path(file_path)
{};
virtual bool process_unknown_string(const char *&unknown_key, uchar* base,
@@ -273,15 +274,15 @@ public:
class Handle_old_incorrect_trigger_table_hook: public Unknown_key_hook
{
public:
- Handle_old_incorrect_trigger_table_hook(char *file_path,
- LEX_STRING *trigger_table_arg)
+ Handle_old_incorrect_trigger_table_hook(const char *file_path,
+ LEX_CSTRING *trigger_table_arg)
:path(file_path), trigger_table_value(trigger_table_arg)
{};
virtual bool process_unknown_string(const char *&unknown_key, uchar* base,
MEM_ROOT *mem_root, const char *end);
private:
- char *path;
- LEX_STRING *trigger_table_value;
+ const char *path;
+ LEX_CSTRING *trigger_table_value;
};
@@ -299,7 +300,7 @@ class Deprecated_trigger_syntax_handler : public Internal_error_handler
private:
char m_message[MYSQL_ERRMSG_SIZE];
- LEX_STRING *m_trigger_name;
+ LEX_CSTRING *m_trigger_name;
public:
@@ -329,7 +330,7 @@ public:
return false;
}
- LEX_STRING *get_trigger_name() { return m_trigger_name; }
+ LEX_CSTRING *get_trigger_name() { return m_trigger_name; }
char *get_error_message() { return m_message; }
};
@@ -525,7 +526,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
}
/* We also don't allow creation of triggers on views. */
- tables->required_type= FRMTYPE_TABLE;
+ tables->required_type= TABLE_TYPE_NORMAL;
/*
Also prevent DROP TRIGGER from opening temporary table which might
shadow the subject table on which trigger to be dropped is defined.
@@ -643,10 +644,10 @@ end:
static void build_trig_stmt_query(THD *thd, TABLE_LIST *tables,
String *stmt_query, String *trigger_def,
- LEX_STRING *trg_definer,
+ LEX_CSTRING *trg_definer,
char trg_definer_holder[])
{
- LEX_STRING stmt_definition;
+ LEX_CSTRING stmt_definition;
LEX *lex= thd->lex;
uint prefix_trimmed, suffix_trimmed;
size_t original_length;
@@ -662,7 +663,7 @@ static void build_trig_stmt_query(THD *thd, TABLE_LIST *tables,
if (lex->create_info.or_replace())
stmt_query->append(STRING_WITH_LEN("OR REPLACE "));
- if (lex->sphead->m_chistics->suid != SP_IS_NOT_SUID)
+ if (lex->sphead->suid() != SP_IS_NOT_SUID)
{
/* SUID trigger */
lex->definer->set_lex_string(trg_definer, trg_definer_holder);
@@ -671,7 +672,7 @@ static void build_trig_stmt_query(THD *thd, TABLE_LIST *tables,
}
else
{
- *trg_definer= empty_lex_str;
+ *trg_definer= empty_clex_str;
}
@@ -736,7 +737,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
LEX *lex= thd->lex;
TABLE *table= tables->table;
char file_buff[FN_REFLEN], trigname_buff[FN_REFLEN];
- LEX_STRING file, trigname_file;
+ LEX_CSTRING file, trigname_file;
char trg_definer_holder[USER_HOST_BUFF_SIZE];
Item_trigger_field *trg_field;
struct st_trigname trigname;
@@ -833,11 +834,13 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
}
else if (lex->create_info.if_not_exists())
{
+ strxnmov(trigname_buff, sizeof(trigname_buff) - 1, tables->db, ".",
+ lex->spname->m_name.str, NullS);
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_TRG_ALREADY_EXISTS,
ER_THD(thd, ER_TRG_ALREADY_EXISTS),
trigname_buff);
- LEX_STRING trg_definer_tmp;
+ LEX_CSTRING trg_definer_tmp;
String trigger_def;
/*
@@ -850,7 +853,9 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
}
else
{
- my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
+ strxnmov(trigname_buff, sizeof(trigname_buff) - 1, tables->db, ".",
+ lex->spname->m_name.str, NullS);
+ my_error(ER_TRG_ALREADY_EXISTS, MYF(0), trigname_buff);
DBUG_RETURN(true);
}
}
@@ -1046,7 +1051,7 @@ bool Table_triggers_list::save_trigger_file(THD *thd, const char *db,
const char *table_name)
{
char file_buff[FN_REFLEN];
- LEX_STRING file;
+ LEX_CSTRING file;
if (create_lists_needed_for_files(thd->mem_root))
return true;
@@ -1066,7 +1071,7 @@ bool Table_triggers_list::save_trigger_file(THD *thd, const char *db,
@param remove_from_list If set, remove trigger if found
*/
-Trigger *Table_triggers_list::find_trigger(const LEX_STRING *name,
+Trigger *Table_triggers_list::find_trigger(const LEX_CSTRING *name,
bool remove_from_list)
{
for (uint i= 0; i < (uint)TRG_EVENT_MAX; i++)
@@ -1121,7 +1126,7 @@ Trigger *Table_triggers_list::find_trigger(const LEX_STRING *name,
bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
String *stmt_query)
{
- const LEX_STRING *sp_name= &thd->lex->spname->m_name; // alias
+ const LEX_CSTRING *sp_name= &thd->lex->spname->m_name; // alias
char path[FN_REFLEN];
Trigger *trigger;
@@ -1294,7 +1299,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
bool names_only)
{
char path_buff[FN_REFLEN];
- LEX_STRING path;
+ LEX_CSTRING path;
File_parser *parser;
LEX_STRING save_db;
DBUG_ENTER("Table_triggers_list::check_n_load");
@@ -1314,7 +1319,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
if (is_equal(&triggers_file_type, parser->type()))
{
Handle_old_incorrect_sql_modes_hook sql_modes_hook(path.str);
- LEX_STRING *trg_create_str;
+ LEX_CSTRING *trg_create_str;
ulonglong *trg_sql_mode, *trg_create_time;
Trigger *trigger;
Table_triggers_list *trigger_list=
@@ -1328,7 +1333,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
&sql_modes_hook))
goto error;
- List_iterator_fast<LEX_STRING> it(trigger_list->definitions_list);
+ List_iterator_fast<LEX_CSTRING> it(trigger_list->definitions_list);
if (!trigger_list->definitions_list.is_empty() &&
(trigger_list->client_cs_names.is_empty() ||
@@ -1347,10 +1352,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
status_var_increment(thd->status_var.feature_trigger);
List_iterator_fast<ulonglong> itm(trigger_list->definition_modes_list);
- List_iterator_fast<LEX_STRING> it_definer(trigger_list->definers_list);
- List_iterator_fast<LEX_STRING> it_client_cs_name(trigger_list->client_cs_names);
- List_iterator_fast<LEX_STRING> it_connection_cl_name(trigger_list->connection_cl_names);
- List_iterator_fast<LEX_STRING> it_db_cl_name(trigger_list->db_cl_names);
+ List_iterator_fast<LEX_CSTRING> it_definer(trigger_list->definers_list);
+ List_iterator_fast<LEX_CSTRING> it_client_cs_name(trigger_list->client_cs_names);
+ List_iterator_fast<LEX_CSTRING> it_connection_cl_name(trigger_list->connection_cl_names);
+ List_iterator_fast<LEX_CSTRING> it_db_cl_name(trigger_list->db_cl_names);
List_iterator_fast<ulonglong> it_create_times(trigger_list->create_times);
LEX *old_lex= thd->lex, lex;
sp_rcontext *save_spcont= thd->spcont;
@@ -1365,7 +1370,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
{
sp_head *sp;
sql_mode_t sql_mode;
- LEX_STRING *trg_definer;
+ LEX_CSTRING *trg_definer;
Trigger_creation_ctx *creation_ctx;
/*
@@ -1382,7 +1387,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd->variables.sql_mode= sql_mode;
Parser_state parser_state;
- if (parser_state.init(thd, trg_create_str->str, trg_create_str->length))
+ if (parser_state.init(thd, (char*) trg_create_str->str,
+ trg_create_str->length))
goto err_with_lex_cleanup;
if (!trigger_list->client_cs_names.is_empty())
@@ -1425,7 +1431,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
lex.set_trg_event_type_for_tables();
if (lex.sphead)
- lex.sphead->set_info(0, 0, &lex.sp_chistics, sql_mode);
+ lex.sphead->m_sql_mode= sql_mode;
if (unlikely(!(trigger= (new (&table->mem_root)
Trigger(trigger_list, lex.sphead)))))
@@ -1437,7 +1443,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
trigger->sql_mode= sql_mode;
trigger->definition= *trg_create_str;
trigger->create_time= trg_create_time ? *trg_create_time : 0;
- trigger->name= sp ? sp->m_name : empty_lex_str;
+ trigger->name= sp ? sp->m_name : empty_clex_str;
trigger->on_table_name.str= (char*) lex.raw_trg_on_table_name_begin;
trigger->on_table_name.length= (lex.raw_trg_on_table_name_end -
lex.raw_trg_on_table_name_begin);
@@ -1460,7 +1466,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
if (parse_error)
{
- LEX_STRING *name;
+ LEX_CSTRING *name;
/*
In case of errors, disable all triggers for the table, but keep
@@ -1479,11 +1485,11 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
goto err_with_lex_cleanup;
}
trigger->definer= ((!trg_definer || !trg_definer->length) ?
- empty_lex_str : *trg_definer);
+ empty_clex_str : *trg_definer);
continue;
}
- sp->set_info(0, 0, &lex.sp_chistics, sql_mode);
+ sp->m_sql_mode= sql_mode;
sp->set_creation_ctx(creation_ctx);
if (!trg_definer || !trg_definer->length)
@@ -1505,15 +1511,15 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
schema.
*/
- sp->set_definer((char*) "", 0);
- trigger->definer= empty_lex_str;
+ sp->set_definer("", 0);
+ trigger->definer= empty_clex_str;
/*
trigger_list without definer information are executed under the
authorization of the invoker.
*/
- sp->m_chistics->suid= SP_IS_NOT_SUID;
+ sp->set_suid(SP_IS_NOT_SUID);
}
else
{
@@ -1618,7 +1624,7 @@ error:
void Table_triggers_list::add_trigger(trg_event_type event,
trg_action_time_type action_time,
trigger_order_type ordering_clause,
- LEX_STRING *anchor_trigger_name,
+ LEX_CSTRING *anchor_trigger_name,
Trigger *trigger)
{
Trigger **parent= &triggers[event][action_time];
@@ -1669,8 +1675,9 @@ void Table_triggers_list::add_trigger(trg_event_type event,
True error
*/
-void Trigger::get_trigger_info(LEX_STRING *trigger_stmt,
- LEX_STRING *trigger_body, LEX_STRING *definer)
+void Trigger::get_trigger_info(LEX_CSTRING *trigger_stmt,
+ LEX_CSTRING *trigger_body,
+ LEX_STRING *definer)
{
DBUG_ENTER("get_trigger_info");
@@ -1684,14 +1691,14 @@ void Trigger::get_trigger_info(LEX_STRING *trigger_stmt,
}
*trigger_body= body->m_body_utf8;
- if (body->m_chistics->suid == SP_IS_NOT_SUID)
+ if (body->suid() == SP_IS_NOT_SUID)
{
*definer= empty_lex_str;
}
else
{
- definer->length= strxmov(definer->str, body->m_definer_user.str, "@",
- body->m_definer_host.str, NullS) - definer->str;
+ definer->length= strxmov(definer->str, body->m_definer.user.str, "@",
+ body->m_definer.host.str, NullS) - definer->str;
}
DBUG_VOID_RETURN;
}
@@ -1722,7 +1729,7 @@ bool add_table_for_trigger(THD *thd,
LEX *lex= thd->lex;
char trn_path_buff[FN_REFLEN];
LEX_STRING trn_path= { trn_path_buff, 0 };
- LEX_STRING tbl_name= null_lex_str;
+ LEX_CSTRING tbl_name= null_clex_str;
DBUG_ENTER("add_table_for_trigger");
@@ -1746,7 +1753,8 @@ bool add_table_for_trigger(THD *thd,
DBUG_RETURN(TRUE);
}
- if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
+ if (load_table_name_for_trigger(thd, trg_name, (LEX_CSTRING*) &trn_path,
+ &tbl_name))
DBUG_RETURN(TRUE);
*table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str,
@@ -1770,7 +1778,8 @@ bool add_table_for_trigger(THD *thd,
True error
*/
-bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name)
+bool Table_triggers_list::drop_all_triggers(THD *thd, const char *db,
+ const char *name)
{
TABLE table;
char path[FN_REFLEN];
@@ -1844,7 +1853,7 @@ struct change_table_name_param
THD *thd;
const char *old_db_name;
const char *new_db_name;
- LEX_STRING *new_table_name;
+ LEX_CSTRING *new_table_name;
Trigger *stopper;
};
@@ -1853,8 +1862,8 @@ bool
Table_triggers_list::change_table_name_in_triggers(THD *thd,
const char *old_db_name,
const char *new_db_name,
- LEX_STRING *old_table_name,
- LEX_STRING *new_table_name)
+ LEX_CSTRING *old_table_name,
+ LEX_CSTRING *new_table_name)
{
struct change_table_name_param param;
sql_mode_t save_sql_mode= thd->variables.sql_mode;
@@ -1886,9 +1895,8 @@ bool Trigger::change_table_name(void* param_arg)
{
change_table_name_param *param= (change_table_name_param*) param_arg;
THD *thd= param->thd;
- LEX_STRING *new_table_name= param->new_table_name;
-
- LEX_STRING *def= &definition, new_def;
+ LEX_CSTRING *new_table_name= param->new_table_name;
+ LEX_CSTRING *def= &definition, new_def;
size_t on_q_table_name_len, before_on_len;
String buff;
@@ -1943,7 +1951,7 @@ bool Trigger::change_table_name(void* param_arg)
Trigger *
Table_triggers_list::change_table_name_in_trignames(const char *old_db_name,
const char *new_db_name,
- LEX_STRING *new_table_name,
+ LEX_CSTRING *new_table_name,
Trigger *trigger)
{
struct change_table_name_param param;
@@ -1962,7 +1970,7 @@ bool Trigger::change_on_table_name(void* param_arg)
char trigname_buff[FN_REFLEN];
struct st_trigname trigname;
- LEX_STRING trigname_file;
+ LEX_CSTRING trigname_file;
if (param->stopper == this)
return 0; // Stop processing
@@ -2052,8 +2060,8 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
result= 1;
goto end;
}
- LEX_STRING old_table_name= { (char *) old_alias, strlen(old_alias) };
- LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
+ LEX_CSTRING old_table_name= { (char *) old_alias, strlen(old_alias) };
+ LEX_CSTRING new_table_name= { (char *) new_table, strlen(new_table) };
/*
Since triggers should be in the same schema as their subject tables
moving table with them between two schemas raises too many questions.
@@ -2464,16 +2472,14 @@ bool check_trn_exists(const LEX_STRING *trn_path)
bool load_table_name_for_trigger(THD *thd,
const sp_name *trg_name,
- const LEX_STRING *trn_path,
- LEX_STRING *tbl_name)
+ const LEX_CSTRING *trn_path,
+ LEX_CSTRING *tbl_name)
{
File_parser *parser;
struct st_trigname trn_data;
-
Handle_old_incorrect_trigger_table_hook trigger_table_hook(
trn_path->str,
&trn_data.trigger_table);
-
DBUG_ENTER("load_table_name_for_trigger");
/* Parse the TRN-file. */
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index 9d1c79cc7cf..8847680c7b2 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -71,7 +71,7 @@ struct st_trg_execution_order
Trigger name referenced in the FOLLOWS/PRECEDES clause of the
CREATE TRIGGER statement.
*/
- LEX_STRING anchor_trigger_name;
+ LEX_CSTRING anchor_trigger_name;
};
@@ -99,15 +99,15 @@ public:
grouped by event and action_time.
*/
Item_trigger_field *trigger_fields;
- LEX_STRING name;
- LEX_STRING on_table_name; /* Raw table name */
- LEX_STRING definition;
- LEX_STRING definer;
+ LEX_CSTRING name;
+ LEX_CSTRING on_table_name; /* Raw table name */
+ LEX_CSTRING definition;
+ LEX_CSTRING definer;
/* Character sets used */
- LEX_STRING client_cs_name;
- LEX_STRING connection_cl_name;
- LEX_STRING db_cl_name;
+ LEX_CSTRING client_cs_name;
+ LEX_CSTRING connection_cl_name;
+ LEX_CSTRING db_cl_name;
GRANT_INFO subject_table_grants;
sql_mode_t sql_mode;
@@ -118,7 +118,7 @@ public:
uint action_order;
bool is_fields_updated_in_trigger(MY_BITMAP *used_fields);
- void get_trigger_info(LEX_STRING *stmt, LEX_STRING *body,
+ void get_trigger_info(LEX_CSTRING *stmt, LEX_CSTRING *body,
LEX_STRING *definer);
/* Functions executed over each active trigger */
bool change_on_table_name(void* param_arg);
@@ -189,7 +189,7 @@ public:
Field responsible for storing triggers definitions in file.
It have to be public because we are using it directly from parser.
*/
- List<LEX_STRING> definitions_list;
+ List<LEX_CSTRING> definitions_list;
/**
List of sql modes for triggers
*/
@@ -197,13 +197,13 @@ public:
/** Create times for triggers */
List<ulonglong> create_times;
- List<LEX_STRING> definers_list;
+ List<LEX_CSTRING> definers_list;
/* Character set context, used for parsing and executing triggers. */
- List<LEX_STRING> client_cs_names;
- List<LEX_STRING> connection_cl_names;
- List<LEX_STRING> db_cl_names;
+ List<LEX_CSTRING> client_cs_names;
+ List<LEX_CSTRING> connection_cl_names;
+ List<LEX_CSTRING> db_cl_names;
/* End of character ser context. */
@@ -227,7 +227,8 @@ public:
static bool check_n_load(THD *thd, const char *db, const char *table_name,
TABLE *table, bool names_only);
- static bool drop_all_triggers(THD *thd, char *db, char *table_name);
+ static bool drop_all_triggers(THD *thd, const char *db,
+ const char *table_name);
static bool change_table_name(THD *thd, const char *db,
const char *old_alias,
const char *old_table,
@@ -236,7 +237,7 @@ public:
void add_trigger(trg_event_type event_type,
trg_action_time_type action_time,
trigger_order_type ordering_clause,
- LEX_STRING *anchor_trigger_name,
+ LEX_CSTRING *anchor_trigger_name,
Trigger *trigger);
Trigger *get_trigger(trg_event_type event_type,
trg_action_time_type action_time)
@@ -279,7 +280,7 @@ public:
bzero(extra_null_bitmap, null_bytes);
}
- Trigger *find_trigger(const LEX_STRING *name, bool remove_from_list);
+ Trigger *find_trigger(const LEX_CSTRING *name, bool remove_from_list);
Trigger* for_all_triggers(Triggers_processor func, void *arg);
@@ -287,13 +288,13 @@ private:
bool prepare_record_accessors(TABLE *table);
Trigger *change_table_name_in_trignames(const char *old_db_name,
const char *new_db_name,
- LEX_STRING *new_table_name,
+ LEX_CSTRING *new_table_name,
Trigger *trigger);
bool change_table_name_in_triggers(THD *thd,
const char *old_db_name,
const char *new_db_name,
- LEX_STRING *old_table_name,
- LEX_STRING *new_table_name);
+ LEX_CSTRING *old_table_name,
+ LEX_CSTRING *new_table_name);
bool check_for_broken_triggers()
{
@@ -324,8 +325,8 @@ bool check_trn_exists(const LEX_STRING *trn_path);
bool load_table_name_for_trigger(THD *thd,
const sp_name *trg_name,
- const LEX_STRING *trn_path,
- LEX_STRING *tbl_name);
+ const LEX_CSTRING *trn_path,
+ LEX_CSTRING *tbl_name);
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
extern const char * const TRG_EXT;
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index c08c75f771a..d4859efc7af 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -38,11 +38,11 @@
*/
static bool fk_info_append_fields(THD *thd, String *str,
- List<LEX_STRING> *fields)
+ List<LEX_CSTRING> *fields)
{
bool res= FALSE;
- LEX_STRING *field;
- List_iterator_fast<LEX_STRING> it(*fields);
+ LEX_CSTRING *field;
+ List_iterator_fast<LEX_CSTRING> it(*fields);
while ((field= it++))
{
@@ -216,7 +216,7 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref,
or writing into the table. Yet, to open a write cursor we need
a thr_lock lock. Allow to open base tables only.
*/
- table_ref->required_type= FRMTYPE_TABLE;
+ table_ref->required_type= TABLE_TYPE_NORMAL;
/*
Ignore pending FLUSH TABLES since we don't want to release
the MDL lock taken above and otherwise there is no way to
@@ -248,8 +248,8 @@ Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref,
table_ref->table->file->print_error(error, MYF(0));
/*
If truncate method is not implemented then we don't binlog the
- statement. If truncation has failed in a transactional engine then also we
- donot binlog the statment. Only in non transactional engine we binlog
+ statement. If truncation has failed in a transactional engine then also
+ we don't binlog the statment. Only in non transactional engine we binlog
inspite of errors.
*/
if (error == HA_ERR_WRONG_COMMAND ||
@@ -311,14 +311,17 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
}
else
{
+ handlerton *hton;
+ bool is_sequence;
+
/* Acquire an exclusive lock. */
DBUG_ASSERT(table_ref->next_global == NULL);
if (lock_table_names(thd, table_ref, NULL,
thd->variables.lock_wait_timeout, 0))
DBUG_RETURN(TRUE);
- handlerton *hton;
- if (!ha_table_exists(thd, table_ref->db, table_ref->table_name, &hton) ||
+ if (!ha_table_exists(thd, table_ref->db, table_ref->table_name,
+ &hton, &is_sequence) ||
hton == view_pseudo_hton)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_ref->db, table_ref->table_name);
@@ -337,7 +340,7 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
*hton_can_recreate= false;
}
else
- *hton_can_recreate= hton->flags & HTON_CAN_RECREATE;
+ *hton_can_recreate= !is_sequence && hton->flags & HTON_CAN_RECREATE;
}
/*
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index d85664568a1..6e99655c28b 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -17,40 +17,237 @@
#include "sql_type.h"
#include "sql_const.h"
#include "sql_class.h"
+#include "sql_time.h"
#include "item.h"
#include "log.h"
-static Type_handler_tiny type_handler_tiny;
-static Type_handler_short type_handler_short;
-static Type_handler_long type_handler_long;
-static Type_handler_longlong type_handler_longlong;
-static Type_handler_int24 type_handler_int24;
-static Type_handler_year type_handler_year;
-static Type_handler_bit type_handler_bit;
-static Type_handler_float type_handler_float;
-static Type_handler_double type_handler_double;
-static Type_handler_time type_handler_time;
-static Type_handler_time2 type_handler_time2;
-static Type_handler_date type_handler_date;
-static Type_handler_newdate type_handler_newdate;
-static Type_handler_datetime type_handler_datetime;
-static Type_handler_datetime2 type_handler_datetime2;
-static Type_handler_timestamp type_handler_timestamp;
-static Type_handler_timestamp2 type_handler_timestamp2;
-static Type_handler_olddecimal type_handler_olddecimal;
-static Type_handler_newdecimal type_handler_newdecimal;
-static Type_handler_null type_handler_null;
-static Type_handler_string type_handler_string;
-static Type_handler_varchar type_handler_varchar;
-static Type_handler_tiny_blob type_handler_tiny_blob;
-static Type_handler_medium_blob type_handler_medium_blob;
-static Type_handler_long_blob type_handler_long_blob;
-static Type_handler_blob type_handler_blob;
+Type_handler_row type_handler_row;
+
+Type_handler_null type_handler_null;
+
+Type_handler_tiny type_handler_tiny;
+Type_handler_short type_handler_short;
+Type_handler_long type_handler_long;
+Type_handler_int24 type_handler_int24;
+Type_handler_longlong type_handler_longlong;
+Type_handler_longlong type_handler_ulonglong; // Only used for CAST() for now
+Type_handler_float type_handler_float;
+Type_handler_double type_handler_double;
+Type_handler_bit type_handler_bit;
+
+Type_handler_olddecimal type_handler_olddecimal;
+Type_handler_newdecimal type_handler_newdecimal;
+
+Type_handler_year type_handler_year;
+Type_handler_time type_handler_time;
+Type_handler_date type_handler_date;
+Type_handler_timestamp type_handler_timestamp;
+Type_handler_timestamp2 type_handler_timestamp2;
+Type_handler_datetime type_handler_datetime;
+Type_handler_time2 type_handler_time2;
+Type_handler_newdate type_handler_newdate;
+Type_handler_datetime2 type_handler_datetime2;
+
+Type_handler_enum type_handler_enum;
+Type_handler_set type_handler_set;
+
+Type_handler_string type_handler_string;
+Type_handler_var_string type_handler_var_string;
+Type_handler_varchar type_handler_varchar;
+
+Type_handler_tiny_blob type_handler_tiny_blob;
+Type_handler_medium_blob type_handler_medium_blob;
+Type_handler_long_blob type_handler_long_blob;
+Type_handler_blob type_handler_blob;
+
#ifdef HAVE_SPATIAL
-static Type_handler_geometry type_handler_geometry;
+Type_handler_geometry type_handler_geometry;
+#endif
+
+
+bool Type_handler_data::init()
+{
+#ifdef HAVE_SPATIAL
+
+#ifndef DBUG_OFF
+ if (m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
+ &type_handler_geometry,
+ &type_handler_geometry) ||
+ m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
+ &type_handler_varchar,
+ &type_handler_long_blob))
+ return true;
+#endif
+
+ return
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_null,
+ &type_handler_geometry) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_geometry,
+ &type_handler_geometry) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_tiny_blob,
+ &type_handler_long_blob) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_blob,
+ &type_handler_long_blob) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_medium_blob,
+ &type_handler_long_blob) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_long_blob,
+ &type_handler_long_blob) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_varchar,
+ &type_handler_long_blob) ||
+ m_type_aggregator_for_result.add(&type_handler_geometry,
+ &type_handler_string,
+ &type_handler_long_blob) ||
+ m_type_aggregator_for_comparison.add(&type_handler_geometry,
+ &type_handler_geometry,
+ &type_handler_geometry) ||
+ m_type_aggregator_for_comparison.add(&type_handler_geometry,
+ &type_handler_null,
+ &type_handler_geometry) ||
+ m_type_aggregator_for_comparison.add(&type_handler_geometry,
+ &type_handler_long_blob,
+ &type_handler_long_blob);
#endif
-static Type_handler_enum type_handler_enum;
-static Type_handler_set type_handler_set;
+ return false;
+}
+
+
+Type_handler_data *type_handler_data= NULL;
+
+
+void Type_std_attributes::set(const Field *field)
+{
+ decimals= field->decimals();
+ unsigned_flag= MY_TEST(field->flags & UNSIGNED_FLAG);
+ collation.set(field->charset(), field->derivation(), field->repertoire());
+ fix_char_length(field->char_length());
+}
+
+
+uint Type_std_attributes::count_max_decimals(Item **item, uint nitems)
+{
+ uint res= 0;
+ for (uint i= 0; i < nitems; i++)
+ set_if_bigger(res, item[i]->decimals);
+ return res;
+}
+
+
+/**
+ Set max_length/decimals of function if function is fixed point and
+ result length/precision depends on argument ones.
+*/
+
+void Type_std_attributes::count_decimal_length(Item **item, uint nitems)
+{
+ int max_int_part= 0;
+ decimals= 0;
+ unsigned_flag= 1;
+ for (uint i=0 ; i < nitems ; i++)
+ {
+ set_if_bigger(decimals, item[i]->decimals);
+ set_if_bigger(max_int_part, item[i]->decimal_int_part());
+ set_if_smaller(unsigned_flag, item[i]->unsigned_flag);
+ }
+ int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
+ fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag));
+}
+
+
+/**
+ Set max_length of if it is maximum length of its arguments.
+*/
+
+void Type_std_attributes::count_only_length(Item **item, uint nitems)
+{
+ uint32 char_length= 0;
+ unsigned_flag= 0;
+ for (uint i= 0; i < nitems ; i++)
+ {
+ set_if_bigger(char_length, item[i]->max_char_length());
+ set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
+ }
+ fix_char_length(char_length);
+}
+
+
+void Type_std_attributes::count_octet_length(Item **item, uint nitems)
+{
+ max_length= 0;
+ unsigned_flag= 0;
+ for (uint i= 0; i < nitems ; i++)
+ {
+ set_if_bigger(max_length, item[i]->max_length);
+ set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
+ }
+}
+
+
+/**
+ Set max_length/decimals of function if function is floating point and
+ result length/precision depends on argument ones.
+*/
+
+void Type_std_attributes::count_real_length(Item **items, uint nitems)
+{
+ uint32 length= 0;
+ decimals= 0;
+ max_length= 0;
+ unsigned_flag= false;
+ for (uint i=0 ; i < nitems ; i++)
+ {
+ if (decimals < FLOATING_POINT_DECIMALS)
+ {
+ set_if_bigger(decimals, items[i]->decimals);
+ /* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
+ set_if_bigger(length, (items[i]->max_length - items[i]->decimals));
+ }
+ set_if_bigger(max_length, items[i]->max_length);
+ }
+ if (decimals < FLOATING_POINT_DECIMALS)
+ {
+ max_length= length;
+ length+= decimals;
+ if (length < max_length) // If previous operation gave overflow
+ max_length= UINT_MAX32;
+ else
+ max_length= length;
+ }
+ // Corner case: COALESCE(DOUBLE(255,4), DOUBLE(255,3)) -> FLOAT(255, 4)
+ set_if_smaller(max_length, MAX_FIELD_CHARLENGTH);
+}
+
+
+/**
+ Calculate max_length and decimals for string functions.
+
+ @param field_type Field type.
+ @param items Argument array.
+ @param nitems Number of arguments.
+
+ @retval False on success, true on error.
+*/
+bool Type_std_attributes::count_string_length(const char *func_name,
+ Item **items, uint nitems)
+{
+ if (agg_arg_charsets_for_string_result(collation, func_name,
+ items, nitems, 1))
+ return true;
+ if (collation.collation == &my_charset_bin)
+ count_octet_length(items, nitems);
+ else
+ count_only_length(items, nitems);
+ decimals= max_length ? NOT_FIXED_DEC : 0;
+ return false;
+}
/**
@@ -68,7 +265,7 @@ static Type_handler_set type_handler_set;
all around the code.
*/
const Type_handler *
-Type_handler::string_type_handler(uint max_octet_length) const
+Type_handler::string_type_handler(uint max_octet_length)
{
if (max_octet_length >= 16777216)
return &type_handler_long_blob;
@@ -78,6 +275,36 @@ Type_handler::string_type_handler(uint max_octet_length) const
}
+const Type_handler *
+Type_handler::varstring_type_handler(const Item *item)
+{
+ if (!item->max_length)
+ return &type_handler_string;
+ if (item->too_big_for_varchar())
+ return blob_type_handler(item->max_length);
+ return &type_handler_varchar;
+}
+
+
+const Type_handler *
+Type_handler::blob_type_handler(uint max_octet_length)
+{
+ if (max_octet_length <= 255)
+ return &type_handler_tiny_blob;
+ if (max_octet_length <= 65535)
+ return &type_handler_blob;
+ if (max_octet_length <= 16777215)
+ return &type_handler_medium_blob;
+ return &type_handler_long_blob;
+}
+
+
+const Type_handler *
+Type_handler::blob_type_handler(const Item *item)
+{
+ return blob_type_handler(item->max_length);
+}
+
/**
This method is used by:
- Item_sum_hybrid, e.g. MAX(item), MIN(item).
@@ -98,19 +325,51 @@ Type_handler_string_result::type_handler_adjusted_to_max_octet_length(
}
+CHARSET_INFO *Type_handler::charset_for_protocol(const Item *item) const
+{
+ /*
+ For backward compatibility, to make numeric
+ data types return "binary" charset in client-side metadata.
+ */
+ return &my_charset_bin;
+}
+
+
+bool
+Type_handler::Item_func_or_sum_illegal_param(const char *funcname) const
+{
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ name().ptr(), funcname);
+ return true;
+}
+
+
+bool
+Type_handler::Item_func_or_sum_illegal_param(const Item_func_or_sum *it) const
+{
+ return Item_func_or_sum_illegal_param(it->func_name());
+}
+
+
+CHARSET_INFO *
+Type_handler_string_result::charset_for_protocol(const Item *item) const
+{
+ return item->collation.collation;
+}
+
+
const Type_handler *
-Type_handler_hybrid_field_type::get_handler_by_result_type(Item_result type)
- const
+Type_handler::get_handler_by_cmp_type(Item_result type)
{
switch (type) {
case REAL_RESULT: return &type_handler_double;
case INT_RESULT: return &type_handler_longlong;
case DECIMAL_RESULT: return &type_handler_newdecimal;
case STRING_RESULT: return &type_handler_long_blob;
- case TIME_RESULT:
- case ROW_RESULT:
- DBUG_ASSERT(0);
+ case TIME_RESULT: return &type_handler_datetime;
+ case ROW_RESULT: return &type_handler_row;
}
+ DBUG_ASSERT(0);
return &type_handler_string;
}
@@ -121,6 +380,502 @@ Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
}
+/***************************************************************************/
+
+/* number of bytes to store second_part part of the TIMESTAMP(N) */
+uint Type_handler_timestamp::m_sec_part_bytes[MAX_DATETIME_PRECISION + 1]=
+ { 0, 1, 1, 2, 2, 3, 3 };
+
+/* number of bytes to store DATETIME(N) */
+uint Type_handler_datetime::m_hires_bytes[MAX_DATETIME_PRECISION + 1]=
+ { 5, 6, 6, 7, 7, 7, 8 };
+
+/* number of bytes to store TIME(N) */
+uint Type_handler_time::m_hires_bytes[MAX_DATETIME_PRECISION + 1]=
+ { 3, 4, 4, 5, 5, 5, 6 };
+
+/***************************************************************************/
+const Name Type_handler_row::m_name_row(C_STRING_WITH_LEN("row"));
+
+const Name Type_handler_null::m_name_null(C_STRING_WITH_LEN("null"));
+
+const Name
+ Type_handler_string::m_name_char(C_STRING_WITH_LEN("char")),
+ Type_handler_var_string::m_name_var_string(C_STRING_WITH_LEN("varchar")),
+ Type_handler_varchar::m_name_varchar(C_STRING_WITH_LEN("varchar")),
+ Type_handler_tiny_blob::m_name_tinyblob(C_STRING_WITH_LEN("tinyblob")),
+ Type_handler_medium_blob::m_name_mediumblob(C_STRING_WITH_LEN("mediumblob")),
+ Type_handler_long_blob::m_name_longblob(C_STRING_WITH_LEN("longblob")),
+ Type_handler_blob::m_name_blob(C_STRING_WITH_LEN("blob"));
+
+const Name
+ Type_handler_enum::m_name_enum(C_STRING_WITH_LEN("enum")),
+ Type_handler_set::m_name_set(C_STRING_WITH_LEN("set"));
+
+const Name
+ Type_handler_tiny::m_name_tiny(C_STRING_WITH_LEN("tinyint")),
+ Type_handler_short::m_name_short(C_STRING_WITH_LEN("smallint")),
+ Type_handler_long::m_name_int(C_STRING_WITH_LEN("int")),
+ Type_handler_longlong::m_name_longlong(C_STRING_WITH_LEN("bigint")),
+ Type_handler_int24::m_name_mediumint(C_STRING_WITH_LEN("mediumint")),
+ Type_handler_year::m_name_year(C_STRING_WITH_LEN("year")),
+ Type_handler_bit::m_name_bit(C_STRING_WITH_LEN("bit"));
+
+const Name
+ Type_handler_float::m_name_float(C_STRING_WITH_LEN("float")),
+ Type_handler_double::m_name_double(C_STRING_WITH_LEN("double"));
+
+const Name
+ Type_handler_olddecimal::m_name_decimal(C_STRING_WITH_LEN("decimal")),
+ Type_handler_newdecimal::m_name_decimal(C_STRING_WITH_LEN("decimal"));
+
+const Name
+ Type_handler_time_common::m_name_time(C_STRING_WITH_LEN("time")),
+ Type_handler_date_common::m_name_date(C_STRING_WITH_LEN("date")),
+ Type_handler_datetime_common::m_name_datetime(C_STRING_WITH_LEN("datetime")),
+ Type_handler_timestamp_common::m_name_timestamp(C_STRING_WITH_LEN("timestamp"));
+
+/***************************************************************************/
+
+const Type_handler *Type_handler_null::type_handler_for_comparison() const
+{
+ return &type_handler_null;
+}
+
+
+const Type_handler *Type_handler_int_result::type_handler_for_comparison() const
+{
+ return &type_handler_longlong;
+}
+
+
+const Type_handler *Type_handler_string_result::type_handler_for_comparison() const
+{
+ return &type_handler_long_blob;
+}
+
+
+const Type_handler *Type_handler_decimal_result::type_handler_for_comparison() const
+{
+ return &type_handler_newdecimal;
+}
+
+
+const Type_handler *Type_handler_real_result::type_handler_for_comparison() const
+{
+ return &type_handler_double;
+}
+
+
+const Type_handler *Type_handler_time_common::type_handler_for_comparison() const
+{
+ return &type_handler_time;
+}
+
+const Type_handler *Type_handler_date_common::type_handler_for_comparison() const
+{
+ return &type_handler_newdate;
+}
+
+
+const Type_handler *Type_handler_datetime_common::type_handler_for_comparison() const
+{
+ return &type_handler_datetime;
+}
+
+
+const Type_handler *Type_handler_timestamp_common::type_handler_for_comparison() const
+{
+ return &type_handler_datetime;
+}
+
+
+const Type_handler *Type_handler_row::type_handler_for_comparison() const
+{
+ return &type_handler_row;
+}
+
+/***************************************************************************/
+
+const Type_handler *Type_handler_typelib::type_handler_for_item_field() const
+{
+ return &type_handler_string;
+}
+
+
+const Type_handler *Type_handler_typelib::cast_to_int_type_handler() const
+{
+ return &type_handler_longlong;
+}
+
+
+/***************************************************************************/
+
+bool
+Type_handler_hybrid_field_type::aggregate_for_result(const Type_handler *other)
+{
+ if (m_type_handler->is_traditional_type() && other->is_traditional_type())
+ {
+ m_type_handler=
+ Type_handler::aggregate_for_result_traditional(m_type_handler, other);
+ return false;
+ }
+ other= type_handler_data->
+ m_type_aggregator_for_result.find_handler(m_type_handler, other);
+ if (!other)
+ return true;
+ m_type_handler= other;
+ return false;
+}
+
+
+const Type_handler *
+Type_handler::type_handler_long_or_longlong(uint max_char_length)
+{
+ if (max_char_length <= MY_INT32_NUM_DECIMAL_DIGITS - 2)
+ return &type_handler_long;
+ return &type_handler_longlong;
+}
+
+/*
+ This method is called for CASE (and its abbreviations) and LEAST/GREATEST
+ when data type aggregation returned LONGLONG and there were some BIT
+ expressions. This helps to adjust the data type from LONGLONG to LONG
+ if all expressions fit.
+*/
+const Type_handler *
+Type_handler::bit_and_int_mixture_handler(uint max_char_length)
+{
+ if (max_char_length <= MY_INT32_NUM_DECIMAL_DIGITS)
+ return &type_handler_long;
+ return &type_handler_longlong;
+}
+
+
+/**
+ @brief Aggregates field types from the array of items.
+
+ @param[in] items array of items to aggregate the type from
+ @param[in] nitems number of items in the array
+ @param[in] treat_bit_as_number - if BIT should be aggregated to a non-BIT
+ counterpart as a LONGLONG number or as a VARBINARY string.
+
+ Currently behaviour depends on the function:
+ - LEAST/GREATEST treat BIT as VARBINARY when
+ aggregating with a non-BIT counterpart.
+ Note, UNION also works this way.
+
+ - CASE, COALESCE, IF, IFNULL treat BIT as LONGLONG when
+ aggregating with a non-BIT counterpart;
+
+ This inconsistency may be changed in the future. See MDEV-8867.
+
+ Note, independently from "treat_bit_as_number":
+ - a single BIT argument gives BIT as a result
+ - two BIT couterparts give BIT as a result
+
+ @details This function aggregates field types from the array of items.
+ Found type is supposed to be used later as the result field type
+ of a multi-argument function.
+ Aggregation itself is performed by Type_handler::aggregate_for_result().
+
+ @note The term "aggregation" is used here in the sense of inferring the
+ result type of a function from its argument types.
+
+ @retval false - on success
+ @retval true - on error
+*/
+
+bool
+Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname,
+ Item **items, uint nitems,
+ bool treat_bit_as_number)
+{
+ bool bit_and_non_bit_mixture_found= false;
+ uint32 max_display_length;
+ if (!nitems || items[0]->result_type() == ROW_RESULT)
+ {
+ DBUG_ASSERT(0);
+ set_handler(&type_handler_null);
+ return true;
+ }
+ set_handler(items[0]->type_handler());
+ max_display_length= items[0]->max_display_length();
+ for (uint i= 1 ; i < nitems ; i++)
+ {
+ const Type_handler *cur= items[i]->type_handler();
+ set_if_bigger(max_display_length, items[i]->max_display_length());
+ if (treat_bit_as_number &&
+ ((type_handler() == &type_handler_bit) ^ (cur == &type_handler_bit)))
+ {
+ bit_and_non_bit_mixture_found= true;
+ if (type_handler() == &type_handler_bit)
+ set_handler(&type_handler_longlong); // BIT + non-BIT
+ else
+ cur= &type_handler_longlong; // non-BIT + BIT
+ }
+ if (aggregate_for_result(cur))
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ type_handler()->name().ptr(), cur->name().ptr(), funcname);
+ return true;
+ }
+ }
+ if (bit_and_non_bit_mixture_found && type_handler() == &type_handler_longlong)
+ set_handler(Type_handler::bit_and_int_mixture_handler(max_display_length));
+ return false;
+}
+
+/**
+ Collect built-in data type handlers for comparison.
+ This method is very similar to item_cmp_type() defined in item.cc.
+ Now they coexist. Later item_cmp_type() will be removed.
+ In addition to item_cmp_type(), this method correctly aggregates
+ TIME with DATETIME/TIMESTAMP/DATE, so no additional find_date_time_item()
+ is needed after this call.
+*/
+
+bool
+Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
+{
+ DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
+ DBUG_ASSERT(h == h->type_handler_for_comparison());
+
+ if (!m_type_handler->is_traditional_type() ||
+ !h->is_traditional_type())
+ {
+ h= type_handler_data->
+ m_type_aggregator_for_comparison.find_handler(m_type_handler, h);
+ if (!h)
+ return true;
+ m_type_handler= h;
+ DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
+ return false;
+ }
+
+ Item_result a= cmp_type();
+ Item_result b= h->cmp_type();
+ if (a == STRING_RESULT && b == STRING_RESULT)
+ m_type_handler= &type_handler_long_blob;
+ else if (a == INT_RESULT && b == INT_RESULT)
+ m_type_handler= &type_handler_longlong;
+ else if (a == ROW_RESULT || b == ROW_RESULT)
+ m_type_handler= &type_handler_row;
+ else if (a == TIME_RESULT || b == TIME_RESULT)
+ {
+ if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
+ {
+ /*
+ We're here if there's only one temporal data type:
+ either m_type_handler or h.
+ */
+ if (b == TIME_RESULT)
+ m_type_handler= h; // Temporal types bit non-temporal types
+ }
+ else
+ {
+ /*
+ We're here if both m_type_handler and h are temporal data types.
+ - If both data types are TIME, we preserve TIME.
+ - If both data types are DATE, we preserve DATE.
+ Preserving DATE is needed for EXPLAIN FORMAT=JSON,
+ to print DATE constants using proper format:
+ 'YYYY-MM-DD' rather than 'YYYY-MM-DD 00:00:00'.
+ */
+ if (m_type_handler->field_type() != h->field_type())
+ m_type_handler= &type_handler_datetime;
+ }
+ }
+ else if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
+ (b == INT_RESULT || b == DECIMAL_RESULT))
+ {
+ m_type_handler= &type_handler_newdecimal;
+ }
+ else
+ m_type_handler= &type_handler_double;
+ DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
+ return false;
+}
+
+
+/**
+ Aggregate data type handler for LEAST/GRATEST.
+ aggregate_for_min_max() is close to aggregate_for_comparison(),
+ but tries to preserve the exact type handler for string, int and temporal
+ data types (instead of converting to super-types).
+ FLOAT is not preserved and is converted to its super-type (DOUBLE).
+ This should probably fixed eventually, for symmetry.
+*/
+
+bool
+Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
+{
+ if (!m_type_handler->is_traditional_type() ||
+ !h->is_traditional_type())
+ {
+ /*
+ If at least one data type is non-traditional,
+ do aggregation for result immediately.
+ For now we suppose that these two expressions:
+ - LEAST(type1, type2)
+ - COALESCE(type1, type2)
+ return the same data type (or both expressions return error)
+ if type1 and/or type2 are non-traditional.
+ This may change in the future.
+ */
+ h= type_handler_data->
+ m_type_aggregator_for_result.find_handler(m_type_handler, h);
+ if (!h)
+ return true;
+ m_type_handler= h;
+ return false;
+ }
+
+ Item_result a= cmp_type();
+ Item_result b= h->cmp_type();
+ DBUG_ASSERT(a != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
+ DBUG_ASSERT(b != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
+
+ if (a == STRING_RESULT && b == STRING_RESULT)
+ m_type_handler=
+ Type_handler::aggregate_for_result_traditional(m_type_handler, h);
+ else if (a == INT_RESULT && b == INT_RESULT)
+ {
+ // BIT aggregates with non-BIT as BIGINT
+ if (m_type_handler != h)
+ {
+ if (m_type_handler == &type_handler_bit)
+ m_type_handler= &type_handler_longlong;
+ else if (h == &type_handler_bit)
+ h= &type_handler_longlong;
+ }
+ m_type_handler=
+ Type_handler::aggregate_for_result_traditional(m_type_handler, h);
+ }
+ else if (a == TIME_RESULT || b == TIME_RESULT)
+ {
+ if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
+ {
+ /*
+ We're here if there's only one temporal data type:
+ either m_type_handler or h.
+ */
+ if (b == TIME_RESULT)
+ m_type_handler= h; // Temporal types bit non-temporal types
+ }
+ else
+ {
+ /*
+ We're here if both m_type_handler and h are temporal data types.
+ */
+ m_type_handler=
+ Type_handler::aggregate_for_result_traditional(m_type_handler, h);
+ }
+ }
+ else if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
+ (b == INT_RESULT || b == DECIMAL_RESULT))
+ {
+ m_type_handler= &type_handler_newdecimal;
+ }
+ else
+ {
+ // Preserve FLOAT if two FLOATs, set to DOUBLE otherwise.
+ if (m_type_handler != &type_handler_float || h != &type_handler_float)
+ m_type_handler= &type_handler_double;
+ }
+ return false;
+}
+
+
+bool
+Type_handler_hybrid_field_type::aggregate_for_min_max(const char *funcname,
+ Item **items, uint nitems)
+{
+ bool bit_and_non_bit_mixture_found= false;
+ uint32 max_display_length;
+ // LEAST/GREATEST require at least two arguments
+ DBUG_ASSERT(nitems > 1);
+ set_handler(items[0]->type_handler());
+ max_display_length= items[0]->max_display_length();
+ for (uint i= 1; i < nitems; i++)
+ {
+ const Type_handler *cur= items[i]->type_handler();
+ set_if_bigger(max_display_length, items[i]->max_display_length());
+ // Check if BIT + non-BIT, or non-BIT + BIT
+ bit_and_non_bit_mixture_found|= (m_type_handler == &type_handler_bit) !=
+ (cur == &type_handler_bit);
+ if (aggregate_for_min_max(cur))
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ type_handler()->name().ptr(), cur->name().ptr(), funcname);
+ return true;
+ }
+ }
+ if (bit_and_non_bit_mixture_found && type_handler() == &type_handler_longlong)
+ set_handler(Type_handler::bit_and_int_mixture_handler(max_display_length));
+ return false;
+}
+
+
+const Type_handler *
+Type_handler::aggregate_for_num_op_traditional(const Type_handler *h0,
+ const Type_handler *h1)
+{
+ Item_result r0= h0->cmp_type();
+ Item_result r1= h1->cmp_type();
+
+ if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
+ r0 == STRING_RESULT || r1 ==STRING_RESULT)
+ return &type_handler_double;
+
+ if (r0 == TIME_RESULT || r1 == TIME_RESULT)
+ return &type_handler_datetime;
+
+ if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
+ return &type_handler_newdecimal;
+
+ DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
+ return &type_handler_longlong;
+}
+
+
+const Type_aggregator::Pair*
+Type_aggregator::find_pair(const Type_handler *handler1,
+ const Type_handler *handler2) const
+{
+ for (uint i= 0; i < m_array.elements(); i++)
+ {
+ const Pair& el= m_array.at(i);
+ if (el.eq(handler1, handler2) ||
+ (m_is_commutative && el.eq(handler2, handler1)))
+ return &el;
+ }
+ return NULL;
+}
+
+
+bool
+Type_handler_hybrid_field_type::aggregate_for_num_op(const Type_aggregator *agg,
+ const Type_handler *h0,
+ const Type_handler *h1)
+{
+ const Type_handler *hres;
+ if (h0->is_traditional_type() && h1->is_traditional_type())
+ {
+ set_handler(Type_handler::aggregate_for_num_op_traditional(h0, h1));
+ return false;
+ }
+ if ((hres= agg->find_handler(h0, h1)))
+ {
+ set_handler(hres);
+ return false;
+ }
+ return true;
+}
+
+
+/***************************************************************************/
+
const Type_handler *
Type_handler::get_handler_by_field_type(enum_field_types type)
{
@@ -235,7 +990,7 @@ Type_handler::make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
Field_double(NULL, item->max_length,
(uchar *) (item->maybe_null ? "" : 0),
item->maybe_null ? 1 : 0, Field::NONE,
- item->name, item->decimals, 0, item->unsigned_flag);
+ &item->name, item->decimals, 0, item->unsigned_flag);
}
@@ -248,7 +1003,7 @@ Type_handler_float::make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
Field_float(NULL, item->max_length,
(uchar *) (item->maybe_null ? "" : 0),
item->maybe_null ? 1 : 0, Field::NONE,
- item->name, item->decimals, 0, item->unsigned_flag);
+ &item->name, item->decimals, 0, item->unsigned_flag);
}
@@ -263,7 +1018,7 @@ Type_handler_decimal_result::make_num_distinct_aggregator_field(
Field_new_decimal(NULL, item->max_length,
(uchar *) (item->maybe_null ? "" : 0),
item->maybe_null ? 1 : 0, Field::NONE,
- item->name, item->decimals, 0, item->unsigned_flag);
+ &item->name, item->decimals, 0, item->unsigned_flag);
}
@@ -280,14 +1035,12 @@ Type_handler_int_result::make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
Field_longlong(NULL, item->max_length,
(uchar *) (item->maybe_null ? "" : 0),
item->maybe_null ? 1 : 0, Field::NONE,
- item->name, 0, item->unsigned_flag);
+ &item->name, 0, item->unsigned_flag);
}
/***********************************************************************/
-#define TMPNAME ""
-
Field *Type_handler_tiny::make_conversion_table_field(TABLE *table,
uint metadata,
const Field *target)
@@ -301,7 +1054,7 @@ Field *Type_handler_tiny::make_conversion_table_field(TABLE *table,
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
return new (table->in_use->mem_root)
Field_tiny(NULL, 4 /*max_length*/, (uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*zerofill*/, unsigned_flag);
+ &empty_clex_str, 0/*zerofill*/, unsigned_flag);
}
@@ -313,7 +1066,7 @@ Field *Type_handler_short::make_conversion_table_field(TABLE *table,
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
return new (table->in_use->mem_root)
Field_short(NULL, 6 /*max_length*/, (uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*zerofill*/, unsigned_flag);
+ &empty_clex_str, 0/*zerofill*/, unsigned_flag);
}
@@ -325,7 +1078,7 @@ Field *Type_handler_int24::make_conversion_table_field(TABLE *table,
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
return new (table->in_use->mem_root)
Field_medium(NULL, 9 /*max_length*/, (uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*zerofill*/, unsigned_flag);
+ &empty_clex_str, 0/*zerofill*/, unsigned_flag);
}
@@ -337,7 +1090,7 @@ Field *Type_handler_long::make_conversion_table_field(TABLE *table,
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
return new (table->in_use->mem_root)
Field_long(NULL, 11 /*max_length*/, (uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*zerofill*/, unsigned_flag);
+ &empty_clex_str, 0/*zerofill*/, unsigned_flag);
}
@@ -349,7 +1102,7 @@ Field *Type_handler_longlong::make_conversion_table_field(TABLE *table,
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
return new (table->in_use->mem_root)
Field_longlong(NULL, 20 /*max_length*/,(uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*zerofill*/, unsigned_flag);
+ &empty_clex_str, 0/*zerofill*/, unsigned_flag);
}
@@ -361,7 +1114,7 @@ Field *Type_handler_float::make_conversion_table_field(TABLE *table,
{
return new (table->in_use->mem_root)
Field_float(NULL, 12 /*max_length*/, (uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*dec*/, 0/*zerofill*/, 0/*unsigned_flag*/);
+ &empty_clex_str, 0/*dec*/, 0/*zerofill*/, 0/*unsigned_flag*/);
}
@@ -372,7 +1125,7 @@ Field *Type_handler_double::make_conversion_table_field(TABLE *table,
{
return new (table->in_use->mem_root)
Field_double(NULL, 22 /*max_length*/, (uchar *) "", 1, Field::NONE,
- TMPNAME, 0/*dec*/, 0/*zerofill*/, 0/*unsigned_flag*/);
+ &empty_clex_str, 0/*dec*/, 0/*zerofill*/, 0/*unsigned_flag*/);
}
@@ -387,7 +1140,7 @@ Field *Type_handler_newdecimal::make_conversion_table_field(TABLE *table,
DBUG_ASSERT(decimals <= DECIMAL_MAX_SCALE);
return new (table->in_use->mem_root)
Field_new_decimal(NULL, max_length, (uchar *) "", 1, Field::NONE,
- TMPNAME, decimals, 0/*zerofill*/, 0/*unsigned*/);
+ &empty_clex_str, decimals, 0/*zerofill*/, 0/*unsigned*/);
}
@@ -403,7 +1156,7 @@ Field *Type_handler_olddecimal::make_conversion_table_field(TABLE *table,
" column Name: %s.%s.%s.",
target->table->s->db.str,
target->table->s->table_name.str,
- target->field_name);
+ target->field_name.str);
return NULL;
}
@@ -414,7 +1167,7 @@ Field *Type_handler_year::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_year(NULL, 4, (uchar *) "", 1, Field::NONE, TMPNAME);
+ Field_year(NULL, 4, (uchar *) "", 1, Field::NONE, &empty_clex_str);
}
@@ -424,7 +1177,7 @@ Field *Type_handler_null::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_null(NULL, 0, Field::NONE, TMPNAME, target->charset());
+ Field_null(NULL, 0, Field::NONE, &empty_clex_str, target->charset());
}
@@ -434,7 +1187,7 @@ Field *Type_handler_timestamp::make_conversion_table_field(TABLE *table,
const
{
return new_Field_timestamp(table->in_use->mem_root, NULL, (uchar *) "", 1,
- Field::NONE, TMPNAME, table->s, target->decimals());
+ Field::NONE, &empty_clex_str, table->s, target->decimals());
}
@@ -445,7 +1198,7 @@ Field *Type_handler_timestamp2::make_conversion_table_field(TABLE *table,
{
return new(table->in_use->mem_root)
Field_timestampf(NULL, (uchar *) "", 1, Field::NONE,
- TMPNAME, table->s, metadata);
+ &empty_clex_str, table->s, metadata);
}
@@ -455,7 +1208,7 @@ Field *Type_handler_newdate::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_newdate(NULL, (uchar *) "", 1, Field::NONE, TMPNAME);
+ Field_newdate(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str);
}
@@ -465,7 +1218,7 @@ Field *Type_handler_date::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_date(NULL, (uchar *) "", 1, Field::NONE, TMPNAME);
+ Field_date(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str);
}
@@ -475,7 +1228,7 @@ Field *Type_handler_time::make_conversion_table_field(TABLE *table,
const
{
return new_Field_time(table->in_use->mem_root, NULL, (uchar *) "", 1,
- Field::NONE, TMPNAME, target->decimals());
+ Field::NONE, &empty_clex_str, target->decimals());
}
@@ -485,7 +1238,7 @@ Field *Type_handler_time2::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_timef(NULL, (uchar *) "", 1, Field::NONE, TMPNAME, metadata);
+ Field_timef(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str, metadata);
}
@@ -495,7 +1248,7 @@ Field *Type_handler_datetime::make_conversion_table_field(TABLE *table,
const
{
return new_Field_datetime(table->in_use->mem_root, NULL, (uchar *) "", 1,
- Field::NONE, TMPNAME, target->decimals());
+ Field::NONE, &empty_clex_str, target->decimals());
}
@@ -506,7 +1259,7 @@ Field *Type_handler_datetime2::make_conversion_table_field(TABLE *table,
{
return new(table->in_use->mem_root)
Field_datetimef(NULL, (uchar *) "", 1,
- Field::NONE, TMPNAME, metadata);
+ Field::NONE, &empty_clex_str, metadata);
}
@@ -519,7 +1272,7 @@ Field *Type_handler_bit::make_conversion_table_field(TABLE *table,
uint32 max_length= 8 * (metadata >> 8U) + (metadata & 0x00ff);
return new(table->in_use->mem_root)
Field_bit_as_char(NULL, max_length, (uchar *) "", 1,
- Field::NONE, TMPNAME);
+ Field::NONE, &empty_clex_str);
}
@@ -532,7 +1285,7 @@ Field *Type_handler_string::make_conversion_table_field(TABLE *table,
uint32 max_length= (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff);
return new(table->in_use->mem_root)
Field_string(NULL, max_length, (uchar *) "", 1,
- Field::NONE, TMPNAME, target->charset());
+ Field::NONE, &empty_clex_str, target->charset());
}
@@ -543,7 +1296,7 @@ Field *Type_handler_varchar::make_conversion_table_field(TABLE *table,
{
return new(table->in_use->mem_root)
Field_varstring(NULL, metadata, HA_VARCHAR_PACKLENGTH(metadata),
- (uchar *) "", 1, Field::NONE, TMPNAME,
+ (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, target->charset());
}
@@ -554,7 +1307,7 @@ Field *Type_handler_tiny_blob::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
+ Field_blob(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, 1, target->charset());
}
@@ -565,7 +1318,7 @@ Field *Type_handler_blob::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
+ Field_blob(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, 2, target->charset());
}
@@ -576,7 +1329,7 @@ Field *Type_handler_medium_blob::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
+ Field_blob(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, 3, target->charset());
}
@@ -587,12 +1340,21 @@ Field *Type_handler_long_blob::make_conversion_table_field(TABLE *table,
const
{
return new(table->in_use->mem_root)
- Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
+ Field_blob(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, 4, target->charset());
}
#ifdef HAVE_SPATIAL
+const Name Type_handler_geometry::m_name_geometry(C_STRING_WITH_LEN("geometry"));
+
+
+const Type_handler *Type_handler_geometry::type_handler_for_comparison() const
+{
+ return &type_handler_geometry;
+}
+
+
Field *Type_handler_geometry::make_conversion_table_field(TABLE *table,
uint metadata,
const Field *target)
@@ -606,7 +1368,7 @@ Field *Type_handler_geometry::make_conversion_table_field(TABLE *table,
The statistics was already incremented when "target" was created.
*/
return new(table->in_use->mem_root)
- Field_geom(NULL, (uchar *) "", 1, Field::NONE, TMPNAME, table->s, 4,
+ Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str, table->s, 4,
((const Field_geom*) target)->geom_type,
((const Field_geom*) target)->srid);
}
@@ -621,7 +1383,7 @@ Field *Type_handler_enum::make_conversion_table_field(TABLE *table,
DBUG_ASSERT(target->real_type() == MYSQL_TYPE_ENUM);
return new(table->in_use->mem_root)
Field_enum(NULL, target->field_length,
- (uchar *) "", 1, Field::NONE, TMPNAME,
+ (uchar *) "", 1, Field::NONE, &empty_clex_str,
metadata & 0x00ff/*pack_length()*/,
((const Field_enum*) target)->typelib, target->charset());
}
@@ -636,7 +1398,3983 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table,
DBUG_ASSERT(target->real_type() == MYSQL_TYPE_SET);
return new(table->in_use->mem_root)
Field_set(NULL, target->field_length,
- (uchar *) "", 1, Field::NONE, TMPNAME,
+ (uchar *) "", 1, Field::NONE, &empty_clex_str,
metadata & 0x00ff/*pack_length()*/,
((const Field_enum*) target)->typelib, target->charset());
}
+
+/*************************************************************************/
+bool Type_handler_null::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return false;
+}
+
+bool Type_handler_tiny::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_int(MAX_TINYINT_WIDTH + def->sign_length());
+}
+
+bool Type_handler_short::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_int(MAX_SMALLINT_WIDTH + def->sign_length());
+}
+
+bool Type_handler_int24::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_int(MAX_MEDIUMINT_WIDTH + def->sign_length());
+}
+
+bool Type_handler_long::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_int(MAX_INT_WIDTH + def->sign_length());
+}
+
+bool Type_handler_longlong::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_int(MAX_BIGINT_WIDTH/*no sign_length() added*/);
+}
+
+bool Type_handler_newdecimal::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_decimal();
+}
+
+bool Type_handler_olddecimal::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ DBUG_ASSERT(0); // Obsolete
+ return true;
+}
+
+bool Type_handler_var_string::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ DBUG_ASSERT(0); // Obsolete
+ return true;
+}
+
+bool Type_handler_varchar::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ /*
+ Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
+ if they don't have a default value
+ */
+ return def->check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_BLOBLENGTH);
+}
+
+bool Type_handler_string::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->check_length(ER_TOO_BIG_FIELDLENGTH, MAX_FIELD_CHARLENGTH);
+}
+
+bool Type_handler_blob_common::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ def->flags|= BLOB_FLAG;
+ return def->check_length(ER_TOO_BIG_DISPLAYWIDTH, MAX_FIELD_BLOBLENGTH);
+}
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ def->flags|= BLOB_FLAG;
+ return false;
+}
+#endif
+
+bool Type_handler_year::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ if (!def->length || def->length != 2)
+ def->length= 4; // Default length
+ def->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
+ return false;
+}
+
+bool Type_handler_float::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_real(MAX_FLOAT_STR_LENGTH);
+}
+
+
+bool Type_handler_double::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_real(DBL_DIG + 7);
+}
+
+bool Type_handler_timestamp_common::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ def->flags|= UNSIGNED_FLAG;
+ return def->fix_attributes_temporal_with_time(MAX_DATETIME_WIDTH);
+}
+
+bool Type_handler_date_common::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ // We don't support creation of MYSQL_TYPE_DATE anymore
+ def->set_handler(&type_handler_newdate);
+ def->length= MAX_DATE_WIDTH;
+ return false;
+}
+
+bool Type_handler_time_common::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_temporal_with_time(MIN_TIME_WIDTH);
+}
+
+bool Type_handler_datetime_common::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_temporal_with_time(MAX_DATETIME_WIDTH);
+}
+
+bool Type_handler_set::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ def->pack_length= get_set_pack_length(def->interval_list.elements);
+ return false;
+}
+
+bool Type_handler_enum::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ def->pack_length= get_enum_pack_length(def->interval_list.elements);
+ return false;
+}
+
+bool Type_handler_bit::
+ Column_definition_fix_attributes(Column_definition *def) const
+{
+ return def->fix_attributes_bit();
+}
+
+/*************************************************************************/
+
+bool Type_handler::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->create_length_to_internal_length_simple();
+ return false;
+}
+
+bool Type_handler_null::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->create_length_to_internal_length_null();
+ return false;
+}
+
+bool Type_handler_newdecimal::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->create_length_to_internal_length_newdecimal();
+ return false;
+}
+
+bool Type_handler_bit::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ return def->prepare_stage1_bit(thd, mem_root, file, table_flags);
+}
+
+bool Type_handler_typelib::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ return def->prepare_stage1_typelib(thd, mem_root, file, table_flags);
+}
+
+
+bool Type_handler_string_result::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ return def->prepare_stage1_string(thd, mem_root, file, table_flags);
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->create_length_to_internal_length_string();
+ return def->prepare_blob_field(thd);
+}
+#endif
+
+
+/*************************************************************************/
+
+bool Type_handler::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_simple();
+ return false;
+}
+
+
+bool Type_handler_null::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_null();
+ return false;
+}
+
+
+bool Type_handler_newdecimal::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_newdecimal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_string();
+ return false;
+}
+
+
+bool Type_handler_typelib::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ def->create_length_to_internal_length_typelib();
+ return false;
+}
+
+
+bool Type_handler_bit::
+ Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+{
+ def->redefine_stage1_common(dup, file, schema);
+ /*
+ If we are replacing a field with a BIT field, we need
+ to initialize pack_flag.
+ */
+ def->pack_flag= FIELDFLAG_NUMBER;
+ if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD))
+ def->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
+ def->create_length_to_internal_length_bit();
+ return false;
+}
+
+
+/*************************************************************************/
+
+bool Type_handler::
+ Column_definition_prepare_stage2_legacy(Column_definition *def,
+ enum_field_types type) const
+{
+ def->pack_flag= f_settype((uint) type);
+ return false;
+}
+
+bool Type_handler::
+ Column_definition_prepare_stage2_legacy_num(Column_definition *def,
+ enum_field_types type) const
+{
+ def->pack_flag= def->pack_flag_numeric(def->decimals) |
+ f_settype((uint) type);
+ return false;
+}
+
+bool Type_handler::
+ Column_definition_prepare_stage2_legacy_real(Column_definition *def,
+ enum_field_types type) const
+{
+ uint dec= def->decimals;
+ /*
+ User specified FLOAT() or DOUBLE() without precision. Change to
+ FLOATING_POINT_DECIMALS to keep things compatible with earlier MariaDB
+ versions.
+ */
+ if (dec >= FLOATING_POINT_DECIMALS)
+ dec= FLOATING_POINT_DECIMALS;
+ def->pack_flag= def->pack_flag_numeric(dec) | f_settype((uint) type);
+ return false;
+}
+
+bool Type_handler_newdecimal::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->pack_flag= def->pack_flag_numeric(def->decimals);
+ return false;
+}
+
+bool Type_handler_blob_common::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_BLOB);
+}
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ if (!(table_flags & HA_CAN_GEOMETRY))
+ {
+ my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
+ return true;
+ }
+ return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_GEOM);
+}
+#endif
+
+bool Type_handler_varchar::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ return def->prepare_stage2_varchar(table_flags);
+}
+
+bool Type_handler_string::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->pack_flag= (def->charset->state & MY_CS_BINSORT) ? FIELDFLAG_BINARY : 0;
+ return false;
+}
+
+bool Type_handler_enum::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ uint dummy;
+ return def->prepare_stage2_typelib("ENUM", FIELDFLAG_INTERVAL, &dummy);
+}
+
+bool Type_handler_set::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ uint dup_count;
+ if (def->prepare_stage2_typelib("SET", FIELDFLAG_BITFIELD, &dup_count))
+ return true;
+ /* Check that count of unique members is not more then 64 */
+ if (def->interval->count - dup_count > sizeof(longlong)*8)
+ {
+ my_error(ER_TOO_BIG_SET, MYF(0), def->field_name.str);
+ return true;
+ }
+ return false;
+}
+
+bool Type_handler_bit::
+ Column_definition_prepare_stage2(Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ /*
+ We have sql_field->pack_flag already set here, see
+ mysql_prepare_create_table().
+ */
+ return false;
+}
+
+/*************************************************************************/
+
+uint32 Type_handler_time::calc_pack_length(uint32 length) const
+{
+ return length > MIN_TIME_WIDTH ?
+ hires_bytes(length - 1 - MIN_TIME_WIDTH) : 3;
+}
+
+uint32 Type_handler_time2::calc_pack_length(uint32 length) const
+{
+ return length > MIN_TIME_WIDTH ?
+ my_time_binary_length(length - MIN_TIME_WIDTH - 1) : 3;
+}
+
+uint32 Type_handler_timestamp::calc_pack_length(uint32 length) const
+{
+ return length > MAX_DATETIME_WIDTH ?
+ 4 + sec_part_bytes(length - 1 - MAX_DATETIME_WIDTH) : 4;
+}
+
+uint32 Type_handler_timestamp2::calc_pack_length(uint32 length) const
+{
+ return length > MAX_DATETIME_WIDTH ?
+ my_timestamp_binary_length(length - MAX_DATETIME_WIDTH - 1) : 4;
+}
+
+uint32 Type_handler_datetime::calc_pack_length(uint32 length) const
+{
+ return length > MAX_DATETIME_WIDTH ?
+ hires_bytes(length - 1 - MAX_DATETIME_WIDTH) : 8;
+}
+
+uint32 Type_handler_datetime2::calc_pack_length(uint32 length) const
+{
+ return length > MAX_DATETIME_WIDTH ?
+ my_datetime_binary_length(length - MAX_DATETIME_WIDTH - 1) : 5;
+}
+
+uint32 Type_handler_tiny_blob::calc_pack_length(uint32 length) const
+{
+ return 1 + portable_sizeof_char_ptr;
+}
+
+uint32 Type_handler_blob::calc_pack_length(uint32 length) const
+{
+ return 2 + portable_sizeof_char_ptr;
+}
+
+uint32 Type_handler_medium_blob::calc_pack_length(uint32 length) const
+{
+ return 3 + portable_sizeof_char_ptr;
+}
+
+uint32 Type_handler_long_blob::calc_pack_length(uint32 length) const
+{
+ return 4 + portable_sizeof_char_ptr;
+}
+
+#ifdef HAVE_SPATIAL
+uint32 Type_handler_geometry::calc_pack_length(uint32 length) const
+{
+ return 4 + portable_sizeof_char_ptr;
+}
+#endif
+
+uint32 Type_handler_newdecimal::calc_pack_length(uint32 length) const
+{
+ abort(); // This shouldn't happen
+ return 0;
+}
+
+uint32 Type_handler_set::calc_pack_length(uint32 length) const
+{
+ abort(); // This shouldn't happen
+ return 0;
+}
+
+uint32 Type_handler_enum::calc_pack_length(uint32 length) const
+{
+ abort(); // This shouldn't happen
+ return 0;
+}
+
+
+/*************************************************************************/
+Field *Type_handler::make_and_init_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ Field *field= make_table_field(name, addr, attr, table);
+ if (field)
+ field->init(table);
+ return field;
+}
+
+
+Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_tiny(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_short::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_short(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_medium(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_long::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_long(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_longlong(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_float::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_float(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_double::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_double(addr.ptr, attr.max_char_length(),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *
+Type_handler_olddecimal::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ /*
+ Currently make_table_field() is used for Item purpose only.
+ On Item level we have type_handler_newdecimal only.
+ For now we have DBUG_ASSERT(0).
+ It will be removed when we reuse Type_handler::make_table_field()
+ in make_field() in field.cc, to open old tables with old decimal.
+ */
+ DBUG_ASSERT(0);
+ return new (table->in_use->mem_root)
+ Field_decimal(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, attr.decimals,
+ 0/*zerofill*/,attr.unsigned_flag);
+}
+
+
+Field *
+Type_handler_newdecimal::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ uint8 dec= attr.decimals;
+ uint8 intg= attr.decimal_precision() - dec;
+ uint32 len= attr.max_char_length();
+
+ /*
+ Trying to put too many digits overall in a DECIMAL(prec,dec)
+ will always throw a warning. We must limit dec to
+ DECIMAL_MAX_SCALE however to prevent an assert() later.
+ */
+
+ if (dec > 0)
+ {
+ signed int overflow;
+
+ dec= MY_MIN(dec, DECIMAL_MAX_SCALE);
+
+ /*
+ If the value still overflows the field with the corrected dec,
+ we'll throw out decimals rather than integers. This is still
+ bad and of course throws a truncation warning.
+ +1: for decimal point
+ */
+
+ const int required_length=
+ my_decimal_precision_to_length(intg + dec, dec, attr.unsigned_flag);
+
+ overflow= required_length - len;
+
+ if (overflow > 0)
+ dec= MY_MAX(0, dec - overflow); // too long, discard fract
+ else
+ /* Corrected value fits. */
+ len= required_length;
+ }
+ return new (table->in_use->mem_root)
+ Field_new_decimal(addr.ptr, len, addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ dec, 0/*zerofill*/, attr.unsigned_flag);
+}
+
+
+Field *Type_handler_year::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_year(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field::NONE, name);
+}
+
+
+Field *Type_handler_null::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_null(addr.ptr, attr.max_length,
+ Field::NONE, name, attr.collation.collation);
+}
+
+
+Field *Type_handler_timestamp::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new_Field_timestamp(table->in_use->mem_root,
+ addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s, attr.decimals);
+}
+
+
+Field *Type_handler_timestamp2::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ /*
+ Will be changed to "new Field_timestampf" when we reuse
+ make_table_field() for make_field() purposes in field.cc.
+ */
+ return new_Field_timestamp(table->in_use->mem_root,
+ addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s, attr.decimals);
+}
+
+
+Field *Type_handler_newdate::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_newdate(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name);
+}
+
+
+Field *Type_handler_date::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ /*
+ DBUG_ASSERT will be removed when we reuse make_table_field()
+ for make_field() in field.cc
+ */
+ DBUG_ASSERT(0);
+ return new (table->in_use->mem_root)
+ Field_date(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name);
+}
+
+
+Field *Type_handler_time::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new_Field_time(table->in_use->mem_root,
+ addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, attr.decimals);
+}
+
+
+Field *Type_handler_time2::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+
+{
+ /*
+ Will be changed to "new Field_timef" when we reuse
+ make_table_field() for make_field() purposes in field.cc.
+ */
+ return new_Field_time(table->in_use->mem_root,
+ addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, attr.decimals);
+}
+
+
+Field *Type_handler_datetime::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new_Field_datetime(table->in_use->mem_root,
+ addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, attr.decimals);
+}
+
+
+Field *Type_handler_datetime2::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ /*
+ Will be changed to "new Field_datetimef" when we reuse
+ make_table_field() for make_field() purposes in field.cc.
+ */
+ return new_Field_datetime(table->in_use->mem_root,
+ addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, attr.decimals);
+}
+
+
+Field *Type_handler_bit::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_bit_as_char(addr.ptr, attr.max_length,
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name);
+}
+
+
+Field *Type_handler_string::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_string(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, attr.collation);
+}
+
+
+Field *Type_handler_varchar::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_varstring(addr.ptr, attr.max_length,
+ HA_VARCHAR_PACKLENGTH(attr.max_length),
+ addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ table->s, attr.collation);
+}
+
+
+Field *Type_handler_tiny_blob::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s,
+ 1, attr.collation);
+}
+
+
+Field *Type_handler_blob::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s,
+ 2, attr.collation);
+}
+
+
+Field *
+Type_handler_medium_blob::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s,
+ 3, attr.collation);
+}
+
+
+Field *Type_handler_long_blob::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ return new (table->in_use->mem_root)
+ Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s,
+ 4, attr.collation);
+}
+
+
+
+#ifdef HAVE_SPATIAL
+Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ return new (table->in_use->mem_root)
+ Field_geom(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field::NONE, name, table->s, 4,
+ (Field::geometry_type) attr.uint_geometry_type(),
+ 0);
+}
+#endif
+
+
+Field *Type_handler_enum::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+{
+ TYPELIB *typelib= attr.get_typelib();
+ DBUG_ASSERT(typelib);
+ return new (table->in_use->mem_root)
+ Field_enum(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ get_enum_pack_length(typelib->count), typelib,
+ attr.collation);
+}
+
+
+Field *Type_handler_set::make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+
+{
+ TYPELIB *typelib= attr.get_typelib();
+ DBUG_ASSERT(typelib);
+ return new (table->in_use->mem_root)
+ Field_set(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field::NONE, name,
+ get_enum_pack_length(typelib->count), typelib,
+ attr.collation);
+}
+
+/*************************************************************************/
+
+uint32 Type_handler_decimal_result::max_display_length(const Item *item) const
+{
+ return item->max_length;
+}
+
+
+uint32 Type_handler_temporal_result::max_display_length(const Item *item) const
+{
+ return item->max_length;
+}
+
+
+uint32 Type_handler_string_result::max_display_length(const Item *item) const
+{
+ return item->max_length;
+}
+
+
+uint32 Type_handler_year::max_display_length(const Item *item) const
+{
+ return item->max_length;
+}
+
+
+uint32 Type_handler_bit::max_display_length(const Item *item) const
+{
+ return item->max_length;
+}
+
+/*************************************************************************/
+
+int Type_handler_time_common::Item_save_in_field(Item *item, Field *field,
+ bool no_conversions) const
+{
+ return item->save_time_in_field(field, no_conversions);
+}
+
+int Type_handler_temporal_with_date::Item_save_in_field(Item *item,
+ Field *field,
+ bool no_conversions)
+ const
+{
+ return item->save_date_in_field(field, no_conversions);
+}
+
+
+int Type_handler_string_result::Item_save_in_field(Item *item, Field *field,
+ bool no_conversions) const
+{
+ return item->save_str_in_field(field, no_conversions);
+}
+
+
+int Type_handler_real_result::Item_save_in_field(Item *item, Field *field,
+ bool no_conversions) const
+{
+ return item->save_real_in_field(field, no_conversions);
+}
+
+
+int Type_handler_decimal_result::Item_save_in_field(Item *item, Field *field,
+ bool no_conversions) const
+{
+ return item->save_decimal_in_field(field, no_conversions);
+}
+
+
+int Type_handler_int_result::Item_save_in_field(Item *item, Field *field,
+ bool no_conversions) const
+{
+ return item->save_int_in_field(field, no_conversions);
+}
+
+
+/***********************************************************************/
+
+bool Type_handler_row::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_row();
+}
+
+bool Type_handler_int_result::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_int();
+}
+
+bool Type_handler_real_result::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_real();
+}
+
+bool Type_handler_decimal_result::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_decimal();
+}
+
+bool Type_handler_string_result::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_string();
+}
+
+bool Type_handler_time_common::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_time();
+}
+
+bool
+Type_handler_temporal_with_date::set_comparator_func(Arg_comparator *cmp) const
+{
+ return cmp->set_cmp_func_datetime();
+}
+
+
+/*************************************************************************/
+
+bool Type_handler_temporal_result::
+ can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const)
+ const
+{
+ if (source->compare_type_handler()->cmp_type() != TIME_RESULT)
+ return false;
+
+ /*
+ Can't rewrite:
+ WHERE COALESCE(time_column)='00:00:00'
+ AND COALESCE(time_column)=DATE'2015-09-11'
+ to
+ WHERE DATE'2015-09-11'='00:00:00'
+ AND COALESCE(time_column)=DATE'2015-09-11'
+ because the left part will erroneously try to parse '00:00:00'
+ as DATE, not as TIME.
+
+ TODO: It could still be rewritten to:
+ WHERE DATE'2015-09-11'=TIME'00:00:00'
+ AND COALESCE(time_column)=DATE'2015-09-11'
+ i.e. we need to replace both target_expr and target_value
+ at the same time. This is not supported yet.
+ */
+ return target_value->cmp_type() == TIME_RESULT;
+}
+
+
+bool Type_handler_string_result::
+ can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const)
+ const
+{
+ if (source->compare_type_handler()->cmp_type() != STRING_RESULT)
+ return false;
+ /*
+ In this example:
+ SET NAMES utf8 COLLATE utf8_german2_ci;
+ DROP TABLE IF EXISTS t1;
+ CREATE TABLE t1 (a CHAR(10) CHARACTER SET utf8);
+ INSERT INTO t1 VALUES ('o-umlaut'),('oe');
+ SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci AND a='oe';
+
+ the query should return only the row with 'oe'.
+ It should not return 'o-umlaut', because 'o-umlaut' does not match
+ the right part of the condition: a='oe'
+ ('o-umlaut' is not equal to 'oe' in utf8_general_ci,
+ which is the collation of the field "a").
+
+ If we change the right part from:
+ ... AND a='oe'
+ to
+ ... AND 'oe' COLLATE utf8_german2_ci='oe'
+ it will be evalulated to TRUE and removed from the condition,
+ so the overall query will be simplified to:
+
+ SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci;
+
+ which will erroneously start to return both 'oe' and 'o-umlaut'.
+ So changing "expr" to "const" is not possible if the effective
+ collations of "target" and "source" are not exactly the same.
+
+ Note, the code before the fix for MDEV-7152 only checked that
+ collations of "source_const" and "target_value" are the same.
+ This was not enough, as the bug report demonstrated.
+ */
+ return
+ target->compare_collation() == source->compare_collation() &&
+ target_value->collation.collation == source_const->collation.collation;
+}
+
+
+bool Type_handler_numeric::
+ can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const)
+ const
+{
+ /*
+ The collations of "target" and "source" do not make sense for numeric
+ data types.
+ */
+ return target->compare_type_handler() == source->compare_type_handler();
+}
+
+
+/*************************************************************************/
+
+Item_cache *
+Type_handler_row::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_row(thd);
+}
+
+Item_cache *
+Type_handler_int_result::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_int(thd, item->type_handler());
+}
+
+Item_cache *
+Type_handler_real_result::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_real(thd);
+}
+
+Item_cache *
+Type_handler_decimal_result::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_decimal(thd);
+}
+
+Item_cache *
+Type_handler_string_result::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_str(thd, item);
+}
+
+Item_cache *
+Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_temporal(thd, item->type_handler());
+}
+
+/*************************************************************************/
+
+bool Type_handler_int_result::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ uint unsigned_flag= items[0]->unsigned_flag;
+ for (uint i= 1; i < nitems; i++)
+ {
+ if (unsigned_flag != items[i]->unsigned_flag)
+ {
+ // Convert a mixture of signed and unsigned int to decimal
+ handler->set_handler(&type_handler_newdecimal);
+ func->aggregate_attributes_decimal(items, nitems);
+ return false;
+ }
+ }
+ func->aggregate_attributes_int(items, nitems);
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_real(items, nitems);
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_decimal(items, nitems);
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ return func->aggregate_attributes_string(func_name, items, nitems);
+}
+
+
+
+/*
+ We can have enum/set type after merging only if we have one enum|set
+ field (or MIN|MAX(enum|set field)) and number of NULL fields
+*/
+bool Type_handler_typelib::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ TYPELIB *typelib= NULL;
+ for (uint i= 0; i < nitems; i++)
+ {
+ if ((typelib= items[i]->get_typelib()))
+ break;
+ }
+ DBUG_ASSERT(typelib); // There must be at least one typelib
+ func->set_typelib(typelib);
+ return func->aggregate_attributes_string(func_name, items, nitems);
+}
+
+
+bool Type_handler_blob_common::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ if (func->aggregate_attributes_string(func_name, items, nitems))
+ return true;
+ handler->set_handler(blob_type_handler(func->max_length));
+ return false;
+}
+
+
+bool Type_handler_date_common::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ func->fix_attributes_date();
+ return false;
+}
+
+
+bool Type_handler_time_common::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_temporal(MIN_TIME_WIDTH, items, nitems);
+ return false;
+}
+
+
+bool Type_handler_datetime_common::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
+ return false;
+}
+
+
+bool Type_handler_timestamp_common::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
+ return false;
+}
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_hybrid_func_fix_attributes(THD *thd,
+ const char *func_name,
+ Type_handler_hybrid_field_type *handler,
+ Type_all_attributes *func,
+ Item **items, uint nitems) const
+{
+ DBUG_ASSERT(nitems > 0);
+ Type_geometry_attributes gattr(items[0]->type_handler(), items[0]);
+ for (uint i= 1; i < nitems; i++)
+ gattr.join(items[i]);
+ func->set_geometry_type(gattr.get_geometry_type());
+ func->collation.set(&my_charset_bin);
+ func->unsigned_flag= false;
+ func->decimals= 0;
+ func->max_length= (uint32) UINT_MAX32;
+ func->set_maybe_null(true);
+ return false;
+}
+#endif
+
+
+/*************************************************************************/
+
+bool Type_handler::
+ Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
+ Item **items, uint nitems) const
+{
+ /*
+ Aggregating attributes for LEAST/GREATES is exactly the same
+ with aggregating for CASE-alike functions (e.g. COALESCE)
+ for the majority of data type handlers.
+ */
+ return Item_hybrid_func_fix_attributes(thd, func->func_name(),
+ func, func, items, nitems);
+}
+
+
+bool Type_handler_real_result::
+ Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
+ Item **items, uint nitems) const
+{
+ /*
+ DOUBLE is an exception and aggregates attributes differently
+ for LEAST/GREATEST vs CASE-alike functions. See the comment in
+ Item_func_min_max::aggregate_attributes_real().
+ */
+ func->aggregate_attributes_real(items, nitems);
+ return false;
+}
+
+/*************************************************************************/
+
+/**
+ MAX/MIN for the traditional numeric types preserve the exact data type
+ from Fields, but do not preserve the exact type from Items:
+ MAX(float_field) -> FLOAT
+ MAX(smallint_field) -> LONGLONG
+ MAX(COALESCE(float_field)) -> DOUBLE
+ MAX(COALESCE(smallint_field)) -> LONGLONG
+ QQ: Items should probably be fixed to preserve the exact type.
+*/
+bool Type_handler_numeric::
+ Item_sum_hybrid_fix_length_and_dec_numeric(Item_sum_hybrid *func,
+ const Type_handler *handler)
+ const
+{
+ Item *item= func->arguments()[0];
+ Item *item2= item->real_item();
+ func->Type_std_attributes::set(item);
+ /* MIN/MAX can return NULL for empty set indepedent of the used column */
+ func->maybe_null= func->null_value= true;
+ if (item2->type() == Item::FIELD_ITEM)
+ func->set_handler(item2->type_handler());
+ else
+ func->set_handler(handler);
+ return false;
+}
+
+
+bool Type_handler_int_result::
+ Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+{
+ return Item_sum_hybrid_fix_length_and_dec_numeric(func,
+ &type_handler_longlong);
+}
+
+
+bool Type_handler_real_result::
+ Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+{
+ (void) Item_sum_hybrid_fix_length_and_dec_numeric(func,
+ &type_handler_double);
+ func->max_length= func->float_length(func->decimals);
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+{
+ return Item_sum_hybrid_fix_length_and_dec_numeric(func,
+ &type_handler_newdecimal);
+}
+
+
+/**
+ MAX(str_field) converts ENUM/SET to CHAR, and preserve all other types
+ for Fields.
+ QQ: This works differently from UNION, which preserve the exact data
+ type for ENUM/SET if the joined ENUM/SET fields are equally defined.
+ Perhaps should be fixed.
+ MAX(str_item) chooses the best suitable string type.
+*/
+bool Type_handler_string_result::
+ Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+{
+ Item *item= func->arguments()[0];
+ Item *item2= item->real_item();
+ func->Type_std_attributes::set(item);
+ func->maybe_null= func->null_value= true;
+ if (item2->type() == Item::FIELD_ITEM)
+ {
+ // Fields: convert ENUM/SET to CHAR, preserve the type otherwise.
+ func->set_handler(item->type_handler());
+ }
+ else
+ {
+ // Items: choose VARCHAR/BLOB/MEDIUMBLOB/LONGBLOB, depending on length.
+ func->set_handler(type_handler_varchar.
+ type_handler_adjusted_to_max_octet_length(func->max_length,
+ func->collation.collation));
+ }
+ return false;
+}
+
+
+/**
+ Traditional temporal types always preserve the type of the argument.
+*/
+bool Type_handler_temporal_result::
+ Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+{
+ Item *item= func->arguments()[0];
+ func->Type_std_attributes::set(item);
+ func->maybe_null= func->null_value= true;
+ func->set_handler(item->type_handler());
+ return false;
+}
+
+
+/*************************************************************************/
+
+bool Type_handler_int_result::
+ Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
+{
+ return Item_func_or_sum_illegal_param("sum");
+}
+#endif
+
+
+/*************************************************************************/
+
+bool Type_handler_int_result::
+ Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
+{
+ return Item_func_or_sum_illegal_param("avg");
+}
+#endif
+
+
+/*************************************************************************/
+
+bool Type_handler_int_result::
+ Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+#endif
+
+
+/*************************************************************************/
+
+longlong Type_handler_real_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_int_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_decimal_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_temporal_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int();
+}
+
+longlong Type_handler_string_result::
+ Item_val_int_signed_typecast(Item *item) const
+{
+ return item->val_int_signed_typecast_from_str();
+}
+
+/*************************************************************************/
+
+longlong Type_handler_real_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_int();
+}
+
+longlong Type_handler_int_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_int();
+}
+
+longlong Type_handler_decimal_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_decimal();
+}
+
+longlong Type_handler_temporal_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_int();
+}
+
+longlong Type_handler_string_result::
+ Item_val_int_unsigned_typecast(Item *item) const
+{
+ return item->val_int_unsigned_typecast_from_str();
+}
+
+/*************************************************************************/
+
+String *
+Type_handler_real_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+ String *str) const
+{
+ return item->val_str_ascii_from_val_real(str);
+}
+
+
+String *
+Type_handler_decimal_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+ String *str) const
+{
+ return item->val_str_ascii_from_val_real(str);
+}
+
+
+String *
+Type_handler_int_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+ String *str) const
+{
+ return item->val_str_ascii_from_val_int(str);
+}
+
+
+String *
+Type_handler_temporal_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+ String *str) const
+{
+ return item->val_str_ascii_from_val_str(str);
+}
+
+
+String *
+Type_handler_string_result::Item_func_hex_val_str_ascii(Item_func_hex *item,
+ String *str) const
+{
+ return item->val_str_ascii_from_val_str(str);
+}
+
+/***************************************************************************/
+
+String *
+Type_handler_decimal_result::Item_func_hybrid_field_type_val_str(
+ Item_func_hybrid_field_type *item,
+ String *str) const
+{
+ return item->val_str_from_decimal_op(str);
+}
+
+
+double
+Type_handler_decimal_result::Item_func_hybrid_field_type_val_real(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_real_from_decimal_op();
+}
+
+
+longlong
+Type_handler_decimal_result::Item_func_hybrid_field_type_val_int(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_int_from_decimal_op();
+}
+
+
+my_decimal *
+Type_handler_decimal_result::Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *item,
+ my_decimal *dec) const
+{
+ return item->val_decimal_from_decimal_op(dec);
+}
+
+
+bool
+Type_handler_decimal_result::Item_func_hybrid_field_type_get_date(
+ Item_func_hybrid_field_type *item,
+ MYSQL_TIME *ltime,
+ ulonglong fuzzydate) const
+{
+ return item->get_date_from_decimal_op(ltime, fuzzydate);
+}
+
+
+/***************************************************************************/
+
+
+String *
+Type_handler_int_result::Item_func_hybrid_field_type_val_str(
+ Item_func_hybrid_field_type *item,
+ String *str) const
+{
+ return item->val_str_from_int_op(str);
+}
+
+
+double
+Type_handler_int_result::Item_func_hybrid_field_type_val_real(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_real_from_int_op();
+}
+
+
+longlong
+Type_handler_int_result::Item_func_hybrid_field_type_val_int(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_int_from_int_op();
+}
+
+
+my_decimal *
+Type_handler_int_result::Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *item,
+ my_decimal *dec) const
+{
+ return item->val_decimal_from_int_op(dec);
+}
+
+
+bool
+Type_handler_int_result::Item_func_hybrid_field_type_get_date(
+ Item_func_hybrid_field_type *item,
+ MYSQL_TIME *ltime,
+ ulonglong fuzzydate) const
+{
+ return item->get_date_from_int_op(ltime, fuzzydate);
+}
+
+
+
+/***************************************************************************/
+
+String *
+Type_handler_real_result::Item_func_hybrid_field_type_val_str(
+ Item_func_hybrid_field_type *item,
+ String *str) const
+{
+ return item->val_str_from_real_op(str);
+}
+
+
+double
+Type_handler_real_result::Item_func_hybrid_field_type_val_real(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_real_from_real_op();
+}
+
+
+longlong
+Type_handler_real_result::Item_func_hybrid_field_type_val_int(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_int_from_real_op();
+}
+
+
+my_decimal *
+Type_handler_real_result::Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *item,
+ my_decimal *dec) const
+{
+ return item->val_decimal_from_real_op(dec);
+}
+
+
+bool
+Type_handler_real_result::Item_func_hybrid_field_type_get_date(
+ Item_func_hybrid_field_type *item,
+ MYSQL_TIME *ltime,
+ ulonglong fuzzydate) const
+{
+ return item->get_date_from_real_op(ltime, fuzzydate);
+}
+
+
+/***************************************************************************/
+
+String *
+Type_handler_temporal_result::Item_func_hybrid_field_type_val_str(
+ Item_func_hybrid_field_type *item,
+ String *str) const
+{
+ return item->val_str_from_date_op(str);
+}
+
+
+double
+Type_handler_temporal_result::Item_func_hybrid_field_type_val_real(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_real_from_date_op();
+}
+
+
+longlong
+Type_handler_temporal_result::Item_func_hybrid_field_type_val_int(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_int_from_date_op();
+}
+
+
+my_decimal *
+Type_handler_temporal_result::Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *item,
+ my_decimal *dec) const
+{
+ return item->val_decimal_from_date_op(dec);
+}
+
+
+bool
+Type_handler_temporal_result::Item_func_hybrid_field_type_get_date(
+ Item_func_hybrid_field_type *item,
+ MYSQL_TIME *ltime,
+ ulonglong fuzzydate) const
+{
+ return item->get_date_from_date_op(ltime, fuzzydate);
+}
+
+
+/***************************************************************************/
+
+String *
+Type_handler_string_result::Item_func_hybrid_field_type_val_str(
+ Item_func_hybrid_field_type *item,
+ String *str) const
+{
+ return item->val_str_from_str_op(str);
+}
+
+
+double
+Type_handler_string_result::Item_func_hybrid_field_type_val_real(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_real_from_str_op();
+}
+
+
+longlong
+Type_handler_string_result::Item_func_hybrid_field_type_val_int(
+ Item_func_hybrid_field_type *item)
+ const
+{
+ return item->val_int_from_str_op();
+}
+
+
+my_decimal *
+Type_handler_string_result::Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *item,
+ my_decimal *dec) const
+{
+ return item->val_decimal_from_str_op(dec);
+}
+
+
+bool
+Type_handler_string_result::Item_func_hybrid_field_type_get_date(
+ Item_func_hybrid_field_type *item,
+ MYSQL_TIME *ltime,
+ ulonglong fuzzydate) const
+{
+ return item->get_date_from_str_op(ltime, fuzzydate);
+}
+
+/***************************************************************************/
+
+bool Type_handler_numeric::
+ Item_func_between_fix_length_and_dec(Item_func_between *func) const
+{
+ return func->fix_length_and_dec_numeric(current_thd);
+}
+
+bool Type_handler_temporal_result::
+ Item_func_between_fix_length_and_dec(Item_func_between *func) const
+{
+ return func->fix_length_and_dec_numeric(current_thd);
+}
+
+bool Type_handler_string_result::
+ Item_func_between_fix_length_and_dec(Item_func_between *func) const
+{
+ return func->fix_length_and_dec_string(current_thd);
+}
+
+
+longlong Type_handler_row::
+ Item_func_between_val_int(Item_func_between *func) const
+{
+ DBUG_ASSERT(0);
+ func->null_value= true;
+ return 0;
+}
+
+longlong Type_handler_string_result::
+ Item_func_between_val_int(Item_func_between *func) const
+{
+ return func->val_int_cmp_string();
+}
+
+longlong Type_handler_temporal_result::
+ Item_func_between_val_int(Item_func_between *func) const
+{
+ return func->val_int_cmp_temporal();
+}
+
+longlong Type_handler_int_result::
+ Item_func_between_val_int(Item_func_between *func) const
+{
+ return func->val_int_cmp_int();
+}
+
+longlong Type_handler_real_result::
+ Item_func_between_val_int(Item_func_between *func) const
+{
+ return func->val_int_cmp_real();
+}
+
+longlong Type_handler_decimal_result::
+ Item_func_between_val_int(Item_func_between *func) const
+{
+ return func->val_int_cmp_decimal();
+}
+
+/***************************************************************************/
+
+cmp_item *Type_handler_int_result::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_int;
+}
+
+cmp_item *Type_handler_real_result::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_real;
+}
+
+cmp_item *Type_handler_decimal_result::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_decimal;
+}
+
+
+cmp_item *Type_handler_string_result::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_sort_string(cs);
+}
+
+cmp_item *Type_handler_row::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_row;
+}
+
+cmp_item *Type_handler_time_common::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_time;
+}
+
+cmp_item *Type_handler_temporal_with_date::make_cmp_item(THD *thd,
+ CHARSET_INFO *cs) const
+{
+ return new (thd->mem_root) cmp_item_datetime;
+}
+
+/***************************************************************************/
+
+static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
+{
+ return cs->coll->strnncollsp(cs,
+ (uchar *) x->ptr(),x->length(),
+ (uchar *) y->ptr(),y->length());
+}
+
+in_vector *Type_handler_string_result::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_string(thd, nargs, (qsort2_cmp) srtcmp_in,
+ func->compare_collation());
+
+}
+
+
+in_vector *Type_handler_int_result::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_longlong(thd, nargs);
+}
+
+
+in_vector *Type_handler_real_result::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_double(thd, nargs);
+}
+
+
+in_vector *Type_handler_decimal_result::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_decimal(thd, nargs);
+}
+
+
+in_vector *Type_handler_time_common::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_time(thd, nargs);
+}
+
+
+in_vector *
+Type_handler_temporal_with_date::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_datetime(thd, nargs);
+}
+
+
+in_vector *Type_handler_row::make_in_vector(THD *thd,
+ const Item_func_in *func,
+ uint nargs) const
+{
+ return new (thd->mem_root) in_row(thd, nargs, 0);
+}
+
+/***************************************************************************/
+
+bool Type_handler_string_result::
+ Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *func) const
+{
+ if (func->agg_all_arg_charsets_for_comparison())
+ return true;
+ if (func->compatible_types_scalar_bisection_possible())
+ {
+ return func->value_list_convert_const_to_int(thd) ||
+ func->fix_for_scalar_comparison_using_bisection(thd);
+ }
+ return
+ func->fix_for_scalar_comparison_using_cmp_items(thd,
+ 1U << (uint) STRING_RESULT);
+}
+
+
+bool Type_handler_int_result::
+ Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *func) const
+{
+ /*
+ Does not need to call value_list_convert_const_to_int()
+ as already handled by int handler.
+ */
+ return func->compatible_types_scalar_bisection_possible() ?
+ func->fix_for_scalar_comparison_using_bisection(thd) :
+ func->fix_for_scalar_comparison_using_cmp_items(thd,
+ 1U << (uint) INT_RESULT);
+}
+
+
+bool Type_handler_real_result::
+ Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *func) const
+{
+ return func->compatible_types_scalar_bisection_possible() ?
+ (func->value_list_convert_const_to_int(thd) ||
+ func->fix_for_scalar_comparison_using_bisection(thd)) :
+ func->fix_for_scalar_comparison_using_cmp_items(thd,
+ 1U << (uint) REAL_RESULT);
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *func) const
+{
+ return func->compatible_types_scalar_bisection_possible() ?
+ (func->value_list_convert_const_to_int(thd) ||
+ func->fix_for_scalar_comparison_using_bisection(thd)) :
+ func->fix_for_scalar_comparison_using_cmp_items(thd,
+ 1U << (uint) DECIMAL_RESULT);
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *func) const
+{
+ return func->compatible_types_scalar_bisection_possible() ?
+ (func->value_list_convert_const_to_int(thd) ||
+ func->fix_for_scalar_comparison_using_bisection(thd)) :
+ func->fix_for_scalar_comparison_using_cmp_items(thd,
+ 1U << (uint) TIME_RESULT);
+}
+
+
+bool Type_handler_row::Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *func) const
+{
+ return func->compatible_types_row_bisection_possible() ?
+ func->fix_for_row_comparison_using_bisection(thd) :
+ func->fix_for_row_comparison_using_cmp_items(thd);
+}
+
+/***************************************************************************/
+
+String *Type_handler_string_result::
+ Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
+{
+ return func->val_str_native(str);
+}
+
+
+String *Type_handler_temporal_result::
+ Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
+{
+ return func->val_string_from_date(str);
+}
+
+
+String *Type_handler_int_result::
+ Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
+{
+ return func->val_string_from_int(str);
+}
+
+
+String *Type_handler_decimal_result::
+ Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
+{
+ return func->val_string_from_decimal(str);
+}
+
+
+String *Type_handler_real_result::
+ Item_func_min_max_val_str(Item_func_min_max *func, String *str) const
+{
+ return func->val_string_from_real(str);
+}
+
+
+double Type_handler_string_result::
+ Item_func_min_max_val_real(Item_func_min_max *func) const
+{
+ return func->val_real_native();
+}
+
+
+double Type_handler_temporal_result::
+ Item_func_min_max_val_real(Item_func_min_max *func) const
+{
+ MYSQL_TIME ltime;
+ if (func->get_date(&ltime, 0))
+ return 0;
+ return TIME_to_double(&ltime);
+}
+
+
+double Type_handler_numeric::
+ Item_func_min_max_val_real(Item_func_min_max *func) const
+{
+ return func->val_real_native();
+}
+
+
+longlong Type_handler_string_result::
+ Item_func_min_max_val_int(Item_func_min_max *func) const
+{
+ return func->val_int_native();
+}
+
+
+longlong Type_handler_temporal_result::
+ Item_func_min_max_val_int(Item_func_min_max *func) const
+{
+ MYSQL_TIME ltime;
+ if (func->get_date(&ltime, 0))
+ return 0;
+ return TIME_to_ulonglong(&ltime);
+}
+
+
+longlong Type_handler_numeric::
+ Item_func_min_max_val_int(Item_func_min_max *func) const
+{
+ return func->val_int_native();
+}
+
+
+my_decimal *Type_handler_string_result::
+ Item_func_min_max_val_decimal(Item_func_min_max *func,
+ my_decimal *dec) const
+{
+ return func->val_decimal_native(dec);
+}
+
+
+my_decimal *Type_handler_numeric::
+ Item_func_min_max_val_decimal(Item_func_min_max *func,
+ my_decimal *dec) const
+{
+ return func->val_decimal_native(dec);
+}
+
+
+my_decimal *Type_handler_temporal_result::
+ Item_func_min_max_val_decimal(Item_func_min_max *func,
+ my_decimal *dec) const
+{
+ MYSQL_TIME ltime;
+ if (func->get_date(&ltime, 0))
+ return 0;
+ return date2my_decimal(&ltime, dec);
+}
+
+
+bool Type_handler_string_result::
+ Item_func_min_max_get_date(Item_func_min_max *func,
+ MYSQL_TIME *ltime, ulonglong fuzzydate) const
+{
+ /*
+ just like ::val_int() method of a string item can be called,
+ for example, SELECT CONCAT("10", "12") + 1,
+ ::get_date() can be called for non-temporal values,
+ for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09"))
+ */
+ return func->Item::get_date(ltime, fuzzydate);
+}
+
+
+bool Type_handler_numeric::
+ Item_func_min_max_get_date(Item_func_min_max *func,
+ MYSQL_TIME *ltime, ulonglong fuzzydate) const
+{
+ return func->Item::get_date(ltime, fuzzydate);
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_min_max_get_date(Item_func_min_max *func,
+ MYSQL_TIME *ltime, ulonglong fuzzydate) const
+{
+ return func->get_date_native(ltime, fuzzydate);
+}
+
+/***************************************************************************/
+
+/**
+ Get a string representation of the Item value.
+ See sql_type.h for details.
+*/
+String *Type_handler_row::
+ print_item_value(THD *thd, Item *item, String *str) const
+{
+ CHARSET_INFO *cs= thd->variables.character_set_client;
+ StringBuffer<STRING_BUFFER_USUAL_SIZE> val(cs);
+ str->append(C_STRING_WITH_LEN("ROW("));
+ for (uint i= 0 ; i < item->cols(); i++)
+ {
+ if (i > 0)
+ str->append(',');
+ Item *elem= item->element_index(i);
+ String *tmp= elem->type_handler()->print_item_value(thd, elem, &val);
+ if (tmp)
+ str->append(*tmp);
+ else
+ str->append(STRING_WITH_LEN("NULL"));
+ }
+ str->append(C_STRING_WITH_LEN(")"));
+ return str;
+}
+
+
+/**
+ Get a string representation of the Item value,
+ using the character string format with its charset and collation, e.g.
+ latin1 'string' COLLATE latin1_german2_ci
+*/
+String *Type_handler::
+ print_item_value_csstr(THD *thd, Item *item, String *str) const
+{
+ String *result= item->val_str(str);
+
+ if (!result)
+ return NULL;
+
+ StringBuffer<STRING_BUFFER_USUAL_SIZE> buf(result->charset());
+ CHARSET_INFO *cs= thd->variables.character_set_client;
+
+ buf.append('_');
+ buf.append(result->charset()->csname);
+ if (cs->escape_with_backslash_is_dangerous)
+ buf.append(' ');
+ append_query_string(cs, &buf, result->ptr(), result->length(),
+ thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES);
+ buf.append(" COLLATE '");
+ buf.append(item->collation.collation->name);
+ buf.append('\'');
+ str->copy(buf);
+
+ return str;
+}
+
+
+String *Type_handler_numeric::
+ print_item_value(THD *thd, Item *item, String *str) const
+{
+ return item->val_str(str);
+}
+
+
+String *Type_handler::
+ print_item_value_temporal(THD *thd, Item *item, String *str,
+ const Name &type_name, String *buf) const
+{
+ String *result= item->val_str(buf);
+ return !result ||
+ str->realloc(type_name.length() + result->length() + 2) ||
+ str->copy(type_name.ptr(), type_name.length(), &my_charset_latin1) ||
+ str->append('\'') ||
+ str->append(result->ptr(), result->length()) ||
+ str->append('\'') ?
+ NULL :
+ str;
+}
+
+
+String *Type_handler_time_common::
+ print_item_value(THD *thd, Item *item, String *str) const
+{
+ StringBuffer<MAX_TIME_FULL_WIDTH+1> buf;
+ return print_item_value_temporal(thd, item, str,
+ Name(C_STRING_WITH_LEN("TIME")), &buf);
+}
+
+
+String *Type_handler_date_common::
+ print_item_value(THD *thd, Item *item, String *str) const
+{
+ StringBuffer<MAX_DATE_WIDTH+1> buf;
+ return print_item_value_temporal(thd, item, str,
+ Name(C_STRING_WITH_LEN("DATE")), &buf);
+}
+
+
+String *Type_handler_datetime_common::
+ print_item_value(THD *thd, Item *item, String *str) const
+{
+ StringBuffer<MAX_DATETIME_FULL_WIDTH+1> buf;
+ return print_item_value_temporal(thd, item, str,
+ Name(C_STRING_WITH_LEN("TIMESTAMP")), &buf);
+}
+
+
+String *Type_handler_timestamp_common::
+ print_item_value(THD *thd, Item *item, String *str) const
+{
+ StringBuffer<MAX_DATETIME_FULL_WIDTH+1> buf;
+ return print_item_value_temporal(thd, item, str,
+ Name(C_STRING_WITH_LEN("TIMESTAMP")), &buf);
+}
+
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ item->fix_arg_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ item->fix_arg_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ item->fix_arg_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ item->fix_arg_double();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ item->fix_arg_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_func_round_fix_length_and_dec(Item_func_round *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+#endif
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ item->fix_length_and_dec_int_or_decimal();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ item->fix_length_and_dec_int_or_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ item->fix_length_and_dec_int_or_decimal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+#endif
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_func_abs_fix_length_and_dec(Item_func_abs *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+#endif
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ DBUG_ASSERT(0);
+ return false;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_func_neg_fix_length_and_dec(Item_func_neg *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+#endif
+
+
+/***************************************************************************/
+
+bool Type_handler::
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+ item->fix_length_and_dec_generic();
+ return false;
+}
+
+
+bool Type_handler::
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+ const Item *arg= item->arguments()[0];
+ if (!arg->unsigned_flag && arg->val_int_min() < 0)
+ {
+ /*
+ Negative arguments produce long results:
+ CAST(1-2 AS UNSIGNED) -> 18446744073709551615
+ */
+ item->max_length= MAX_BIGINT_WIDTH;
+ return false;
+ }
+ item->fix_length_and_dec_generic();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+ item->fix_length_and_dec_string();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+ const Item *arg= item->arguments()[0];
+ if (!arg->unsigned_flag && // Not HEX hybrid
+ arg->max_char_length() > 1) // Can be negative
+ {
+ // String arguments can give long results: '-1' -> 18446744073709551614
+ item->max_length= MAX_BIGINT_WIDTH;
+ return false;
+ }
+ item->fix_length_and_dec_string();
+ return false;
+}
+
+bool Type_handler_real_result::
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler::
+ Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const
+{
+ item->fix_length_and_dec_generic();
+ return false;
+}
+
+
+bool Type_handler::
+ Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
+{
+ item->fix_length_and_dec_generic();
+ return false;
+}
+
+
+bool Type_handler::
+ Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
+{
+ item->fix_length_and_dec_str();
+ return false;
+}
+
+
+bool Type_handler_numeric::
+ Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
+{
+ item->fix_length_and_dec_numeric();
+ return false;
+}
+
+
+bool Type_handler::
+ Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
+{
+ uint dec= item->decimals == NOT_FIXED_DEC ?
+ item->arguments()[0]->time_precision() :
+ item->decimals;
+ item->fix_attributes_temporal(MIN_TIME_WIDTH, dec);
+ item->maybe_null= true;
+ return false;
+}
+
+
+bool Type_handler::
+ Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const
+{
+ item->fix_attributes_temporal(MAX_DATE_WIDTH, 0);
+ item->maybe_null= true;
+ return false;
+}
+
+
+bool Type_handler::
+ Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item)
+ const
+{
+ uint dec= item->decimals == NOT_FIXED_DEC ?
+ item->arguments()[0]->datetime_precision() :
+ item->decimals;
+ item->fix_attributes_temporal(MAX_DATETIME_WIDTH, dec);
+ item->maybe_null= true;
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+
+bool Type_handler_geometry::
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+ Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+ Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+ Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
+{
+ if (item->cast_charset() != &my_charset_bin)
+ return Item_func_or_sum_illegal_param(item); // CAST(geom AS CHAR)
+ item->fix_length_and_dec_str();
+ return false; // CAST(geom AS BINARY)
+}
+
+
+bool Type_handler_geometry::
+ Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+
+
+
+bool Type_handler_geometry::
+ Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const
+{
+ return Item_func_or_sum_illegal_param(item);
+}
+
+
+bool Type_handler_geometry::
+ Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item)
+ const
+{
+ return Item_func_or_sum_illegal_param(item);
+
+}
+
+#endif /* HAVE_SPATIAL */
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
+{
+ DBUG_ASSERT(0);
+ return true;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
+{
+ item->fix_length_and_dec_temporal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
+{
+ DBUG_ASSERT(0);
+ return true;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
+{
+ item->fix_length_and_dec_temporal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
+{
+ DBUG_ASSERT(0);
+ return true;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
+{
+ item->fix_length_and_dec_temporal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_div_fix_length_and_dec(Item_func_div *item) const
+{
+ DBUG_ASSERT(0);
+ return true;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_div_fix_length_and_dec(Item_func_div *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_div_fix_length_and_dec(Item_func_div *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_div_fix_length_and_dec(Item_func_div *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_div_fix_length_and_dec(Item_func_div *item) const
+{
+ item->fix_length_and_dec_temporal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_div_fix_length_and_dec(Item_func_div *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
+{
+ DBUG_ASSERT(0);
+ return true;
+}
+
+
+bool Type_handler_int_result::
+ Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
+{
+ item->fix_length_and_dec_int();
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
+{
+ item->fix_length_and_dec_decimal();
+ return false;
+}
+
+
+bool Type_handler_temporal_result::
+ Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
+{
+ item->fix_length_and_dec_temporal();
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
+{
+ item->fix_length_and_dec_double();
+ return false;
+}
+
+/***************************************************************************/
+
+uint Type_handler::Item_time_precision(Item *item) const
+{
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+
+uint Type_handler::Item_datetime_precision(Item *item) const
+{
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+
+uint Type_handler_string_result::Item_temporal_precision(Item *item,
+ bool is_time) const
+{
+ MYSQL_TIME ltime;
+ StringBuffer<64> buf;
+ String *tmp;
+ MYSQL_TIME_STATUS status;
+ DBUG_ASSERT(item->fixed);
+ if ((tmp= item->val_str(&buf)) &&
+ !(is_time ?
+ str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
+ &ltime, TIME_TIME_ONLY, &status) :
+ str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
+ &ltime, TIME_FUZZY_DATES, &status)))
+ return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+/***************************************************************************/
+
+uint Type_handler::Item_decimal_scale(const Item *item) const
+{
+ return item->decimals < NOT_FIXED_DEC ?
+ item->decimals :
+ MY_MIN(item->max_length, DECIMAL_MAX_SCALE);
+}
+
+uint Type_handler_temporal_result::
+ Item_decimal_scale_with_seconds(const Item *item) const
+{
+ return item->decimals < NOT_FIXED_DEC ?
+ item->decimals :
+ TIME_SECOND_PART_DIGITS;
+}
+
+uint Type_handler::Item_divisor_precision_increment(const Item *item) const
+{
+ return item->decimals;
+}
+
+uint Type_handler_temporal_result::
+ Item_divisor_precision_increment_with_seconds(const Item *item) const
+{
+ return item->decimals < NOT_FIXED_DEC ?
+ item->decimals :
+ TIME_SECOND_PART_DIGITS;
+}
+
+/***************************************************************************/
+
+uint Type_handler_string_result::Item_decimal_precision(const Item *item) const
+{
+ uint res= item->max_char_length();
+ /*
+ Return at least one decimal digit, even if Item::max_char_length()
+ returned 0. This is important to avoid attempts to create fields of types
+ INT(0) or DECIMAL(0,0) when converting NULL or empty strings to INT/DECIMAL:
+ CREATE TABLE t1 AS SELECT CONVERT(NULL,SIGNED) AS a;
+ */
+ return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
+}
+
+uint Type_handler_real_result::Item_decimal_precision(const Item *item) const
+{
+ uint res= item->max_char_length();
+ return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1;
+}
+
+uint Type_handler_decimal_result::Item_decimal_precision(const Item *item) const
+{
+ uint prec= my_decimal_length_to_precision(item->max_char_length(),
+ item->decimals,
+ item->unsigned_flag);
+ return MY_MIN(prec, DECIMAL_MAX_PRECISION);
+}
+
+uint Type_handler_int_result::Item_decimal_precision(const Item *item) const
+{
+ uint prec= my_decimal_length_to_precision(item->max_char_length(),
+ item->decimals,
+ item->unsigned_flag);
+ return MY_MIN(prec, DECIMAL_MAX_PRECISION);
+}
+
+uint Type_handler_time_common::Item_decimal_precision(const Item *item) const
+{
+ return 7 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+uint Type_handler_date_common::Item_decimal_precision(const Item *item) const
+{
+ return 8;
+}
+
+uint Type_handler_datetime_common::Item_decimal_precision(const Item *item) const
+{
+ return 14 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+uint Type_handler_timestamp_common::Item_decimal_precision(const Item *item) const
+{
+ return 14 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+}
+
+/***************************************************************************/
+
+bool Type_handler_real_result::
+ subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+{
+ DBUG_ASSERT(inner->cmp_type() == REAL_RESULT);
+ return outer->cmp_type() == REAL_RESULT;
+}
+
+
+bool Type_handler_int_result::
+ subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+{
+ DBUG_ASSERT(inner->cmp_type() == INT_RESULT);
+ return outer->cmp_type() == INT_RESULT;
+}
+
+
+bool Type_handler_decimal_result::
+ subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+{
+ DBUG_ASSERT(inner->cmp_type() == DECIMAL_RESULT);
+ return outer->cmp_type() == DECIMAL_RESULT;
+}
+
+
+bool Type_handler_string_result::
+ subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+{
+ DBUG_ASSERT(inner->cmp_type() == STRING_RESULT);
+ return outer->cmp_type() == STRING_RESULT &&
+ outer->collation.collation == inner->collation.collation &&
+ /*
+ Materialization also is unable to work when create_tmp_table() will
+ create a blob column because item->max_length is too big.
+ The following test is copied from varstring_type_handler().
+ */
+ !inner->too_big_for_varchar();
+}
+
+
+bool Type_handler_temporal_result::
+ subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+{
+ DBUG_ASSERT(inner->cmp_type() == TIME_RESULT);
+ return mysql_timestamp_type() ==
+ outer->type_handler()->mysql_timestamp_type();
+}
+
+/***************************************************************************/
+
+
+const Type_handler *
+Type_handler_null::type_handler_for_tmp_table(const Item *item) const
+{
+ return &type_handler_string;
+}
+
+
+const Type_handler *
+Type_handler_null::type_handler_for_union(const Item *item) const
+{
+ return &type_handler_string;
+}
+
+
+const Type_handler *
+Type_handler_olddecimal::type_handler_for_tmp_table(const Item *item) const
+{
+ return &type_handler_newdecimal;
+}
+
+const Type_handler *
+Type_handler_olddecimal::type_handler_for_union(const Item *item) const
+{
+ return &type_handler_newdecimal;
+}
+
+
+/***************************************************************************/
+
+bool Type_handler::check_null(const Item *item, st_value *value) const
+{
+ if (item->null_value)
+ {
+ value->m_type= DYN_COL_NULL;
+ return true;
+ }
+ return false;
+}
+
+
+bool Type_handler_null::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= DYN_COL_NULL;
+ return true;
+}
+
+
+bool Type_handler_row::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ DBUG_ASSERT(0);
+ value->m_type= DYN_COL_NULL;
+ return true;
+}
+
+
+bool Type_handler_int_result::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= item->unsigned_flag ? DYN_COL_UINT : DYN_COL_INT;
+ value->value.m_longlong= item->val_int();
+ return check_null(item, value);
+}
+
+
+bool Type_handler_real_result::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= DYN_COL_DOUBLE;
+ value->value.m_double= item->val_real();
+ return check_null(item, value);
+}
+
+
+bool Type_handler_decimal_result::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= DYN_COL_DECIMAL;
+ my_decimal *dec= item->val_decimal(&value->m_decimal);
+ if (dec != &value->m_decimal && !item->null_value)
+ my_decimal2decimal(dec, &value->m_decimal);
+ return check_null(item, value);
+}
+
+
+bool Type_handler_string_result::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= DYN_COL_STRING;
+ String *str= item->val_str(&value->m_string);
+ if (str != &value->m_string && !item->null_value)
+ value->m_string.set(str->ptr(), str->length(), str->charset());
+ return check_null(item, value);
+}
+
+
+bool Type_handler_temporal_with_date::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= DYN_COL_DATETIME;
+ item->get_date(&value->value.m_time, sql_mode_for_dates(current_thd));
+ return check_null(item, value);
+}
+
+
+bool Type_handler_time_common::
+ Item_save_in_value(Item *item, st_value *value) const
+{
+ value->m_type= DYN_COL_DATETIME;
+ item->get_time(&value->value.m_time);
+ return check_null(item, value);
+}
+
+/***************************************************************************/
+
+bool Type_handler_row::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ DBUG_ASSERT(0);
+ param->set_null();
+ return true;
+}
+
+
+bool Type_handler_real_result::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ param->unsigned_flag= attr->unsigned_flag;
+ param->set_double(val->value.m_double);
+ param->set_handler(&type_handler_double);
+ return false;
+}
+
+
+bool Type_handler_int_result::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ param->unsigned_flag= attr->unsigned_flag;
+ param->set_int(val->value.m_longlong, MY_INT64_NUM_DECIMAL_DIGITS);
+ param->set_handler(&type_handler_longlong);
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ param->unsigned_flag= attr->unsigned_flag;
+ param->set_decimal(&val->m_decimal, attr->unsigned_flag);
+ param->set_handler(&type_handler_newdecimal);
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ param->unsigned_flag= false;
+ param->value.cs_info.set(thd, attr->collation.collation);
+ /*
+ Exact value of max_length is not known unless data is converted to
+ charset of connection, so we have to set it later.
+ */
+ param->set_handler(&type_handler_varchar);
+ return param->set_str(val->m_string.ptr(), val->m_string.length());
+}
+
+
+bool Type_handler_temporal_result::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ param->unsigned_flag= attr->unsigned_flag;
+ param->set_time(&val->value.m_time, attr->max_length, attr->decimals);
+ param->set_handler(this);
+ return false;
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *val) const
+{
+ param->unsigned_flag= false;
+ param->value.cs_info.set(thd, &my_charset_bin);
+ param->set_handler(&type_handler_geometry);
+ param->set_geometry_type(attr->uint_geometry_type());
+ return param->set_str(val->m_string.ptr(), val->m_string.length());
+}
+#endif
+
+/***************************************************************************/
+
+bool Type_handler_null::
+ Item_send(Item *item, Protocol *protocol, st_value *buf) const
+{
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_str(Item *item, Protocol *protocol, st_value *buf) const
+{
+ String *res;
+ if ((res= item->val_str(&buf->m_string)))
+ {
+ DBUG_ASSERT(!item->null_value);
+ return protocol->store(res->ptr(), res->length(), res->charset());
+ }
+ DBUG_ASSERT(item->null_value);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_tiny(Item *item, Protocol *protocol, st_value *buf) const
+{
+ longlong nr= item->val_int();
+ if (!item->null_value)
+ return protocol->store_tiny(nr);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_short(Item *item, Protocol *protocol, st_value *buf) const
+{
+ longlong nr= item->val_int();
+ if (!item->null_value)
+ return protocol->store_short(nr);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_long(Item *item, Protocol *protocol, st_value *buf) const
+{
+ longlong nr= item->val_int();
+ if (!item->null_value)
+ return protocol->store_long(nr);
+ return protocol->store_null();
+}
+
+bool Type_handler::
+ Item_send_longlong(Item *item, Protocol *protocol, st_value *buf) const
+{
+ longlong nr= item->val_int();
+ if (!item->null_value)
+ return protocol->store_longlong(nr, item->unsigned_flag);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_float(Item *item, Protocol *protocol, st_value *buf) const
+{
+ float nr= (float) item->val_real();
+ if (!item->null_value)
+ return protocol->store(nr, item->decimals, &buf->m_string);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_double(Item *item, Protocol *protocol, st_value *buf) const
+{
+ double nr= item->val_real();
+ if (!item->null_value)
+ return protocol->store(nr, item->decimals, &buf->m_string);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const
+{
+ item->get_date(&buf->value.m_time, sql_mode_for_dates(current_thd));
+ if (!item->null_value)
+ return protocol->store(&buf->value.m_time, item->decimals);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_date(Item *item, Protocol *protocol, st_value *buf) const
+{
+ item->get_date(&buf->value.m_time, sql_mode_for_dates(current_thd));
+ if (!item->null_value)
+ return protocol->store_date(&buf->value.m_time);
+ return protocol->store_null();
+}
+
+
+bool Type_handler::
+ Item_send_time(Item *item, Protocol *protocol, st_value *buf) const
+{
+ item->get_time(&buf->value.m_time);
+ if (!item->null_value)
+ return protocol->store_time(&buf->value.m_time, item->decimals);
+ return protocol->store_null();
+}
+
+/***************************************************************************/
+
+Item *Type_handler_int_result::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ longlong result= item->val_int();
+ if (item->null_value)
+ return new (thd->mem_root) Item_null(thd, item->name.str);
+ return new (thd->mem_root) Item_int(thd, item->name.str, result,
+ item->max_length);
+}
+
+
+Item *Type_handler_real_result::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ double result= item->val_real();
+ if (item->null_value)
+ return new (thd->mem_root) Item_null(thd, item->name.str);
+ return new (thd->mem_root) Item_float(thd, item->name.str, result,
+ item->decimals, item->max_length);
+}
+
+
+Item *Type_handler_decimal_result::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ my_decimal decimal_value;
+ my_decimal *result= item->val_decimal(&decimal_value);
+ if (item->null_value)
+ return new (thd->mem_root) Item_null(thd, item->name.str);
+ return new (thd->mem_root) Item_decimal(thd, item->name.str, result,
+ item->max_length, item->decimals);
+}
+
+
+Item *Type_handler_string_result::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ StringBuffer<MAX_FIELD_WIDTH> tmp;
+ String *result= item->val_str(&tmp);
+ if (item->null_value)
+ return new (thd->mem_root) Item_null(thd, item->name.str);
+ uint length= result->length();
+ char *tmp_str= thd->strmake(result->ptr(), length);
+ return new (thd->mem_root) Item_string(thd, item->name.str,
+ tmp_str, length, result->charset());
+}
+
+
+Item *Type_handler_time_common::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ Item_cache_temporal *cache;
+ longlong value= item->val_time_packed();
+ if (item->null_value)
+ return new (thd->mem_root) Item_null(thd, item->name.str);
+ cache= new (thd->mem_root) Item_cache_temporal(thd, this);
+ if (cache)
+ cache->store_packed(value, item);
+ return cache;
+}
+
+
+Item *Type_handler_temporal_with_date::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ Item_cache_temporal *cache;
+ longlong value= item->val_datetime_packed();
+ if (item->null_value)
+ return new (thd->mem_root) Item_null(thd, item->name.str);
+ cache= new (thd->mem_root) Item_cache_temporal(thd, this);
+ if (cache)
+ cache->store_packed(value, item);
+ return cache;
+}
+
+
+Item *Type_handler_row::
+ make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const
+{
+ if (item->type() == Item::ROW_ITEM && cmp->type() == Item::ROW_ITEM)
+ {
+ /*
+ Substitute constants only in Item_row's. Don't affect other Items
+ with ROW_RESULT (eg Item_singlerow_subselect).
+
+ For such Items more optimal is to detect if it is constant and replace
+ it with Item_row. This would optimize queries like this:
+ SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
+ */
+ Item_row *item_row= (Item_row*) item;
+ Item_row *comp_item_row= (Item_row*) cmp;
+ uint col;
+ /*
+ If item and comp_item are both Item_row's and have same number of cols
+ then process items in Item_row one by one.
+ We can't ignore NULL values here as this item may be used with <=>, in
+ which case NULL's are significant.
+ */
+ DBUG_ASSERT(item->result_type() == cmp->result_type());
+ DBUG_ASSERT(item_row->cols() == comp_item_row->cols());
+ col= item_row->cols();
+ while (col-- > 0)
+ resolve_const_item(thd, item_row->addr(col),
+ comp_item_row->element_index(col));
+ }
+ return NULL;
+}
+
+/***************************************************************************/
+
+static const char* item_name(Item *a, String *str)
+{
+ if (a->name.str)
+ return a->name.str;
+ str->length(0);
+ a->print(str, QT_ORDINARY);
+ return str->c_ptr_safe();
+}
+
+
+static void wrong_precision_error(uint errcode, Item *a,
+ ulonglong number, uint maximum)
+{
+ StringBuffer<1024> buf(system_charset_info);
+ my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
+}
+
+
+/**
+ Get precision and scale for a declaration
+
+ return
+ 0 ok
+ 1 error
+*/
+
+bool get_length_and_scale(ulonglong length, ulonglong decimals,
+ ulong *out_length, uint *out_decimals,
+ uint max_precision, uint max_scale,
+ Item *a)
+{
+ if (length > (ulonglong) max_precision)
+ {
+ wrong_precision_error(ER_TOO_BIG_PRECISION, a, length, max_precision);
+ return 1;
+ }
+ if (decimals > (ulonglong) max_scale)
+ {
+ wrong_precision_error(ER_TOO_BIG_SCALE, a, decimals, max_scale);
+ return 1;
+ }
+
+ *out_decimals= (uint) decimals;
+ my_decimal_trim(&length, out_decimals);
+ *out_length= (ulong) length;
+
+ if (*out_length < *out_decimals)
+ {
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
+ return 1;
+ }
+ return 0;
+}
+
+
+Item *Type_handler_longlong::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ if (this != &type_handler_ulonglong)
+ return new (thd->mem_root) Item_func_signed(thd, item);
+ return new (thd->mem_root) Item_func_unsigned(thd, item);
+
+}
+
+
+Item *Type_handler_date_common::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ return new (thd->mem_root) Item_date_typecast(thd, item);
+}
+
+
+
+Item *Type_handler_time_common::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ if (attr.decimals() > MAX_DATETIME_PRECISION)
+ {
+ wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(),
+ MAX_DATETIME_PRECISION);
+ return 0;
+ }
+ return new (thd->mem_root)
+ Item_time_typecast(thd, item, (uint) attr.decimals());
+}
+
+
+Item *Type_handler_datetime_common::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ if (attr.decimals() > MAX_DATETIME_PRECISION)
+ {
+ wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(),
+ MAX_DATETIME_PRECISION);
+ return 0;
+ }
+ return new (thd->mem_root)
+ Item_datetime_typecast(thd, item, (uint) attr.decimals());
+
+}
+
+
+Item *Type_handler_decimal_result::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ ulong len;
+ uint dec;
+ if (get_length_and_scale(attr.length(), attr.decimals(), &len, &dec,
+ DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE, item))
+ return NULL;
+ return new (thd->mem_root) Item_decimal_typecast(thd, item, len, dec);
+}
+
+
+Item *Type_handler_double::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ ulong len;
+ uint dec;
+ if (!attr.length_specified())
+ return new (thd->mem_root) Item_double_typecast(thd, item,
+ DBL_DIG + 7,
+ NOT_FIXED_DEC);
+
+ if (get_length_and_scale(attr.length(), attr.decimals(), &len, &dec,
+ DECIMAL_MAX_PRECISION, NOT_FIXED_DEC - 1, item))
+ return NULL;
+ return new (thd->mem_root) Item_double_typecast(thd, item, len, dec);
+}
+
+
+Item *Type_handler_long_blob::
+ create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+{
+ int len= -1;
+ CHARSET_INFO *real_cs= attr.charset() ?
+ attr.charset() :
+ thd->variables.collation_connection;
+ if (attr.length_specified())
+ {
+ if (attr.length() > MAX_FIELD_BLOBLENGTH)
+ {
+ char buff[1024];
+ String buf(buff, sizeof(buff), system_charset_info);
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), item_name(item, &buf),
+ MAX_FIELD_BLOBLENGTH);
+ return NULL;
+ }
+ len= (int) attr.length();
+ }
+ return new (thd->mem_root) Item_char_typecast(thd, item, len, real_cs);
+}
+
+/***************************************************************************/
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 596c338720e..27fb8a8f7da 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -22,35 +22,694 @@
#include "mysqld.h"
+#include "sql_array.h"
+#include "sql_const.h"
+#include "my_time.h"
class Field;
+class Column_definition;
class Item;
-class Type_std_attributes;
+class Item_param;
+class Item_cache;
+class Item_func_or_sum;
+class Item_sum_hybrid;
+class Item_sum_sum;
+class Item_sum_avg;
+class Item_sum_variance;
+class Item_func_hex;
+class Item_hybrid_func;
+class Item_func_min_max;
+class Item_func_hybrid_field_type;
+class Item_bool_func2;
+class Item_func_between;
+class Item_func_in;
+class Item_func_round;
+class Item_func_int_val;
+class Item_func_abs;
+class Item_func_neg;
+class Item_func_signed;
+class Item_func_unsigned;
+class Item_double_typecast;
+class Item_decimal_typecast;
+class Item_char_typecast;
+class Item_time_typecast;
+class Item_date_typecast;
+class Item_datetime_typecast;
+class Item_func_plus;
+class Item_func_minus;
+class Item_func_mul;
+class Item_func_div;
+class Item_func_mod;
+class cmp_item;
+class in_vector;
+class Type_handler_hybrid_field_type;
class Sort_param;
+class Arg_comparator;
+struct st_value;
+class Protocol;
+class handler;
+struct Schema_specification_st;
struct TABLE;
struct SORT_FIELD_ATTR;
+
+/*
+ Flags for collation aggregation modes, used in TDCollation::agg():
+
+ MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
+ MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
+ (i.e. constant).
+ MY_COLL_ALLOW_CONV - allow any kind of conversion
+ (combination of the above two)
+ MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to
+ @@character_set_connection
+ MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE
+ (e.g. when aggregating for comparison)
+ MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV
+ and MY_COLL_DISALLOW_NONE
+*/
+
+#define MY_COLL_ALLOW_SUPERSET_CONV 1
+#define MY_COLL_ALLOW_COERCIBLE_CONV 2
+#define MY_COLL_DISALLOW_NONE 4
+#define MY_COLL_ALLOW_NUMERIC_CONV 8
+
+#define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV)
+#define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE)
+
+
+#define my_charset_numeric my_charset_latin1
+#define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII
+
+
+enum Derivation
+{
+ DERIVATION_IGNORABLE= 6,
+ DERIVATION_NUMERIC= 5,
+ DERIVATION_COERCIBLE= 4,
+ DERIVATION_SYSCONST= 3,
+ DERIVATION_IMPLICIT= 2,
+ DERIVATION_NONE= 1,
+ DERIVATION_EXPLICIT= 0
+};
+
+
+/**
+ "Declared Type Collation"
+ A combination of collation and its derivation.
+*/
+
+class DTCollation {
+public:
+ CHARSET_INFO *collation;
+ enum Derivation derivation;
+ uint repertoire;
+
+ void set_repertoire_from_charset(CHARSET_INFO *cs)
+ {
+ repertoire= cs->state & MY_CS_PUREASCII ?
+ MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
+ }
+ DTCollation()
+ {
+ collation= &my_charset_bin;
+ derivation= DERIVATION_NONE;
+ repertoire= MY_REPERTOIRE_UNICODE30;
+ }
+ DTCollation(CHARSET_INFO *collation_arg)
+ {
+ /*
+ This constructor version is used in combination with Field constructors,
+ to pass "CHARSET_INFO" instead of the full DTCollation.
+ Therefore, derivation is set to DERIVATION_IMPLICIT, which is the
+ proper derivation for table fields.
+ We should eventually remove all code pieces that pass "CHARSET_INFO"
+ (e.g. in storage engine sources) and fix to pass the full DTCollation
+ instead. Then, this constructor can be removed.
+ */
+ collation= collation_arg;
+ derivation= DERIVATION_IMPLICIT;
+ repertoire= my_charset_repertoire(collation_arg);
+ }
+ DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg)
+ {
+ collation= collation_arg;
+ derivation= derivation_arg;
+ set_repertoire_from_charset(collation_arg);
+ }
+ DTCollation(CHARSET_INFO *collation_arg,
+ Derivation derivation_arg,
+ uint repertoire_arg)
+ :collation(collation_arg),
+ derivation(derivation_arg),
+ repertoire(repertoire_arg)
+ { }
+ void set(const DTCollation &dt)
+ {
+ collation= dt.collation;
+ derivation= dt.derivation;
+ repertoire= dt.repertoire;
+ }
+ void set(CHARSET_INFO *collation_arg, Derivation derivation_arg)
+ {
+ collation= collation_arg;
+ derivation= derivation_arg;
+ set_repertoire_from_charset(collation_arg);
+ }
+ void set(CHARSET_INFO *collation_arg,
+ Derivation derivation_arg,
+ uint repertoire_arg)
+ {
+ collation= collation_arg;
+ derivation= derivation_arg;
+ repertoire= repertoire_arg;
+ }
+ void set_numeric()
+ {
+ collation= &my_charset_numeric;
+ derivation= DERIVATION_NUMERIC;
+ repertoire= MY_REPERTOIRE_NUMERIC;
+ }
+ void set(CHARSET_INFO *collation_arg)
+ {
+ collation= collation_arg;
+ set_repertoire_from_charset(collation_arg);
+ }
+ void set(Derivation derivation_arg)
+ { derivation= derivation_arg; }
+ bool aggregate(const DTCollation &dt, uint flags= 0);
+ bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0)
+ { set(dt1); return aggregate(dt2, flags); }
+ const char *derivation_name() const
+ {
+ switch(derivation)
+ {
+ case DERIVATION_NUMERIC: return "NUMERIC";
+ case DERIVATION_IGNORABLE: return "IGNORABLE";
+ case DERIVATION_COERCIBLE: return "COERCIBLE";
+ case DERIVATION_IMPLICIT: return "IMPLICIT";
+ case DERIVATION_SYSCONST: return "SYSCONST";
+ case DERIVATION_EXPLICIT: return "EXPLICIT";
+ case DERIVATION_NONE: return "NONE";
+ default: return "UNKNOWN";
+ }
+ }
+ int sortcmp(const String *s, const String *t) const
+ {
+ return collation->coll->strnncollsp(collation,
+ (uchar *) s->ptr(), s->length(),
+ (uchar *) t->ptr(), t->length());
+ }
+};
+
+
+static inline uint32
+char_to_byte_length_safe(size_t char_length_arg, uint32 mbmaxlen_arg)
+{
+ ulonglong tmp= ((ulonglong) char_length_arg) * mbmaxlen_arg;
+ return tmp > UINT_MAX32 ? UINT_MAX32 : static_cast<uint32>(tmp);
+}
+
+/**
+ A class to store type attributes for the standard data types.
+ Does not include attributes for the extended data types
+ such as ENUM, SET, GEOMETRY.
+*/
+class Type_std_attributes
+{
+public:
+ DTCollation collation;
+ uint decimals;
+ /*
+ The maximum value length in characters multiplied by collation->mbmaxlen.
+ Almost always it's the maximum value length in bytes.
+ */
+ uint32 max_length;
+ bool unsigned_flag;
+ Type_std_attributes()
+ :collation(&my_charset_bin, DERIVATION_COERCIBLE),
+ decimals(0), max_length(0), unsigned_flag(false)
+ { }
+ Type_std_attributes(const Type_std_attributes *other)
+ :collation(other->collation),
+ decimals(other->decimals),
+ max_length(other->max_length),
+ unsigned_flag(other->unsigned_flag)
+ { }
+ Type_std_attributes(uint32 max_length_arg, uint decimals_arg,
+ bool unsigned_flag_arg, const DTCollation &dtc)
+ :collation(dtc),
+ decimals(decimals_arg),
+ max_length(max_length_arg),
+ unsigned_flag(unsigned_flag_arg)
+ { }
+ void set(const Type_std_attributes *other)
+ {
+ *this= *other;
+ }
+ void set(const Type_std_attributes &other)
+ {
+ *this= other;
+ }
+ void set(const Field *field);
+ uint32 max_char_length() const
+ { return max_length / collation.collation->mbmaxlen; }
+ void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs)
+ {
+ max_length= char_to_byte_length_safe(max_char_length_arg, cs->mbmaxlen);
+ collation.collation= cs;
+ }
+ void fix_char_length(uint32 max_char_length_arg)
+ {
+ max_length= char_to_byte_length_safe(max_char_length_arg,
+ collation.collation->mbmaxlen);
+ }
+ void fix_char_length_temporal_not_fixed_dec(uint int_part_length, uint dec)
+ {
+ uint char_length= int_part_length;
+ if ((decimals= dec))
+ {
+ if (decimals == NOT_FIXED_DEC)
+ char_length+= TIME_SECOND_PART_DIGITS + 1;
+ else
+ {
+ set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
+ char_length+= decimals + 1;
+ }
+ }
+ fix_char_length(char_length);
+ }
+ void fix_attributes_temporal_not_fixed_dec(uint int_part_length, uint dec)
+ {
+ collation.set_numeric();
+ unsigned_flag= 0;
+ fix_char_length_temporal_not_fixed_dec(int_part_length, dec);
+ }
+ void fix_attributes_time_not_fixed_dec(uint dec)
+ {
+ fix_attributes_temporal_not_fixed_dec(MIN_TIME_WIDTH, dec);
+ }
+ void fix_attributes_datetime_not_fixed_dec(uint dec)
+ {
+ fix_attributes_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
+ }
+ void fix_attributes_temporal(uint int_part_length, uint dec)
+ {
+ collation.set_numeric();
+ unsigned_flag= 0;
+ decimals= MY_MIN(dec, TIME_SECOND_PART_DIGITS);
+ max_length= decimals + int_part_length + (dec ? 1 : 0);
+ }
+ void fix_attributes_date()
+ {
+ fix_attributes_temporal(MAX_DATE_WIDTH, 0);
+ }
+ void fix_attributes_time(uint dec)
+ {
+ fix_attributes_temporal(MIN_TIME_WIDTH, dec);
+ }
+ void fix_attributes_datetime(uint dec)
+ {
+ fix_attributes_temporal(MAX_DATETIME_WIDTH, dec);
+ }
+
+ void count_only_length(Item **item, uint nitems);
+ void count_octet_length(Item **item, uint nitems);
+ void count_real_length(Item **item, uint nitems);
+ void count_decimal_length(Item **item, uint nitems);
+ bool count_string_length(const char *func_name, Item **item, uint nitems);
+ uint count_max_decimals(Item **item, uint nitems);
+
+ void aggregate_attributes_int(Item **items, uint nitems)
+ {
+ collation.set_numeric();
+ count_only_length(items, nitems);
+ decimals= 0;
+ }
+ void aggregate_attributes_real(Item **items, uint nitems)
+ {
+ collation.set_numeric();
+ count_real_length(items, nitems);
+ }
+ void aggregate_attributes_decimal(Item **items, uint nitems)
+ {
+ collation.set_numeric();
+ count_decimal_length(items, nitems);
+ }
+ bool aggregate_attributes_string(const char *func_name,
+ Item **item, uint nitems)
+ {
+ return count_string_length(func_name, item, nitems);
+ }
+ void aggregate_attributes_temporal(uint int_part_length,
+ Item **item, uint nitems)
+ {
+ fix_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
+ }
+
+ bool agg_item_collations(DTCollation &c, const char *name,
+ Item **items, uint nitems,
+ uint flags, int item_sep);
+ bool agg_item_set_converter(const DTCollation &coll, const char *fname,
+ Item **args, uint nargs,
+ uint flags, int item_sep);
+
+ /*
+ Collect arguments' character sets together.
+ We allow to apply automatic character set conversion in some cases.
+ The conditions when conversion is possible are:
+ - arguments A and B have different charsets
+ - A wins according to coercibility rules
+ (i.e. a column is stronger than a string constant,
+ an explicit COLLATE clause is stronger than a column)
+ - character set of A is either superset for character set of B,
+ or B is a string constant which can be converted into the
+ character set of A without data loss.
+
+ If all of the above is true, then it's possible to convert
+ B into the character set of A, and then compare according
+ to the collation of A.
+
+ For functions with more than two arguments:
+
+ collect(A,B,C) ::= collect(collect(A,B),C)
+
+ Since this function calls THD::change_item_tree() on the passed Item **
+ pointers, it is necessary to pass the original Item **'s, not copies.
+ Otherwise their values will not be properly restored (see BUG#20769).
+ If the items are not consecutive (eg. args[2] and args[5]), use the
+ item_sep argument, ie.
+
+ agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
+ */
+ bool agg_arg_charsets(DTCollation &c, const char *func_name,
+ Item **items, uint nitems,
+ uint flags, int item_sep)
+ {
+ if (agg_item_collations(c, func_name, items, nitems, flags, item_sep))
+ return true;
+ return agg_item_set_converter(c, func_name, items, nitems, flags, item_sep);
+ }
+ /*
+ Aggregate arguments for string result, e.g: CONCAT(a,b)
+ - convert to @@character_set_connection if all arguments are numbers
+ - allow DERIVATION_NONE
+ */
+ bool agg_arg_charsets_for_string_result(DTCollation &c, const char *func_name,
+ Item **items, uint nitems,
+ int item_sep)
+ {
+ uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
+ MY_COLL_ALLOW_COERCIBLE_CONV |
+ MY_COLL_ALLOW_NUMERIC_CONV;
+ return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep);
+ }
+ /*
+ Aggregate arguments for string result, when some comparison
+ is involved internally, e.g: REPLACE(a,b,c)
+ - convert to @@character_set_connection if all arguments are numbers
+ - disallow DERIVATION_NONE
+ */
+ bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c,
+ const char *func_name,
+ Item **items,
+ uint nitems,
+ int item_sep)
+ {
+ uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
+ MY_COLL_ALLOW_COERCIBLE_CONV |
+ MY_COLL_ALLOW_NUMERIC_CONV |
+ MY_COLL_DISALLOW_NONE;
+ return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep);
+ }
+
+ /*
+ Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b
+ - don't convert to @@character_set_connection if all arguments are numbers
+ - don't allow DERIVATION_NONE
+ */
+ bool agg_arg_charsets_for_comparison(DTCollation &c,
+ const char *func_name,
+ Item **items, uint nitems,
+ int item_sep)
+ {
+ uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
+ MY_COLL_ALLOW_COERCIBLE_CONV |
+ MY_COLL_DISALLOW_NONE;
+ return agg_arg_charsets(c, func_name, items, nitems, flags, item_sep);
+ }
+
+};
+
+
+class Type_all_attributes: public Type_std_attributes
+{
+public:
+ Type_all_attributes()
+ :Type_std_attributes()
+ { }
+ Type_all_attributes(const Type_all_attributes *other)
+ :Type_std_attributes(other)
+ { }
+ virtual ~Type_all_attributes() {}
+ virtual void set_maybe_null(bool maybe_null_arg)= 0;
+ // Returns total number of decimal digits
+ virtual uint decimal_precision() const= 0;
+ /*
+ Field::geometry_type is not visible here.
+ Let's use an "uint" wrapper for now. Later when we move Field_geom
+ into a plugin, this method will be replaced to some generic
+ datatype indepented method.
+ */
+ virtual uint uint_geometry_type() const= 0;
+ virtual void set_geometry_type(uint type)= 0;
+ virtual TYPELIB *get_typelib() const= 0;
+ virtual void set_typelib(TYPELIB *typelib)= 0;
+};
+
+
+class Type_cast_attributes
+{
+ CHARSET_INFO *m_charset;
+ ulonglong m_length;
+ ulonglong m_decimals;
+ bool m_length_specified;
+ bool m_decimals_specified;
+public:
+ Type_cast_attributes(const char *c_len, const char *c_dec, CHARSET_INFO *cs)
+ :m_charset(cs), m_length(0), m_decimals(0),
+ m_length_specified(false), m_decimals_specified(false)
+ {
+ set_length_and_dec(c_len, c_dec);
+ }
+ Type_cast_attributes(CHARSET_INFO *cs)
+ :m_charset(cs), m_length(0), m_decimals(0),
+ m_length_specified(false), m_decimals_specified(false)
+ { }
+ void set_length_and_dec(const char *c_len, const char *c_dec)
+ {
+ int error;
+ /*
+ We don't have to check for error here as sql_yacc.yy has guaranteed
+ that the values are in range of ulonglong
+ */
+ if ((m_length_specified= (c_len != NULL)))
+ m_length= (ulonglong) my_strtoll10(c_len, NULL, &error);
+ if ((m_decimals_specified= (c_dec != NULL)))
+ m_decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
+ }
+ CHARSET_INFO *charset() const { return m_charset; }
+ bool length_specified() const { return m_length_specified; }
+ bool decimals_specified() const { return m_decimals_specified; }
+ ulonglong length() const { return m_length; }
+ ulonglong decimals() const { return m_decimals; }
+};
+
+
+class Name: private LEX_CSTRING
+{
+public:
+ Name(const char *str_arg, uint length_arg)
+ {
+ LEX_CSTRING::str= str_arg;
+ LEX_CSTRING::length= length_arg;
+ }
+ const char *ptr() const { return LEX_CSTRING::str; }
+ uint length() const { return LEX_CSTRING::length; }
+};
+
+
+class Record_addr
+{
+public:
+ uchar *ptr; // Position to field in record
+ /**
+ Byte where the @c NULL bit is stored inside a record. If this Field is a
+ @c NOT @c NULL field, this member is @c NULL.
+ */
+ uchar *null_ptr;
+ uchar null_bit; // Bit used to test null bit
+ Record_addr(uchar *ptr_arg,
+ uchar *null_ptr_arg,
+ uchar null_bit_arg)
+ :ptr(ptr_arg),
+ null_ptr(null_ptr_arg),
+ null_bit(null_bit_arg)
+ { }
+ Record_addr(bool maybe_null)
+ :ptr(NULL),
+ null_ptr(maybe_null ? (uchar*) "" : 0),
+ null_bit(0)
+ { }
+};
+
+
class Type_handler
{
protected:
- const Type_handler *string_type_handler(uint max_octet_length) const;
+ String *print_item_value_csstr(THD *thd, Item *item, String *str) const;
+ String *print_item_value_temporal(THD *thd, Item *item, String *str,
+ const Name &type_name, String *buf) const;
void make_sort_key_longlong(uchar *to,
bool maybe_null, bool null_value,
bool unsigned_flag,
longlong value) const;
+ bool
+ Item_func_or_sum_illegal_param(const char *name) const;
+ bool
+ Item_func_or_sum_illegal_param(const Item_func_or_sum *) const;
+ bool check_null(const Item *item, st_value *value) const;
+ bool Item_send_str(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_tiny(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_short(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_long(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_longlong(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_float(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_double(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const;
+ bool Column_definition_prepare_stage2_legacy(Column_definition *c,
+ enum_field_types type)
+ const;
+ bool Column_definition_prepare_stage2_legacy_num(Column_definition *c,
+ enum_field_types type)
+ const;
+ bool Column_definition_prepare_stage2_legacy_real(Column_definition *c,
+ enum_field_types type)
+ const;
public:
+ static const Type_handler *blob_type_handler(uint max_octet_length);
+ static const Type_handler *string_type_handler(uint max_octet_length);
+ static const Type_handler *bit_and_int_mixture_handler(uint max_char_len);
+ static const Type_handler *type_handler_long_or_longlong(uint max_char_len);
+ /**
+ Return a string type handler for Item
+ If too_big_for_varchar() returns a BLOB variant, according to length.
+ If max_length > 0 create a VARCHAR(n)
+ If max_length == 0 create a CHAR(0)
+ @param item - the Item to get the handler to.
+ */
+ static const Type_handler *varstring_type_handler(const Item *item);
+ static const Type_handler *blob_type_handler(const Item *item);
static const Type_handler *get_handler_by_field_type(enum_field_types type);
static const Type_handler *get_handler_by_real_type(enum_field_types type);
+ static const Type_handler *get_handler_by_cmp_type(Item_result type);
+ static const Type_handler *get_handler_by_result_type(Item_result type)
+ {
+ /*
+ As result_type() returns STRING_RESULT for temporal Items,
+ type should never be equal to TIME_RESULT here.
+ */
+ DBUG_ASSERT(type != TIME_RESULT);
+ return get_handler_by_cmp_type(type);
+ }
+ static const
+ Type_handler *aggregate_for_result_traditional(const Type_handler *h1,
+ const Type_handler *h2);
+ static const
+ Type_handler *aggregate_for_num_op_traditional(const Type_handler *h1,
+ const Type_handler *h2);
+
+ virtual const Name name() const= 0;
virtual enum_field_types field_type() const= 0;
virtual enum_field_types real_field_type() const { return field_type(); }
virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0;
+ virtual enum_mysql_timestamp_type mysql_timestamp_type() const
+ {
+ return MYSQL_TIMESTAMP_ERROR;
+ }
+ virtual bool is_timestamp_type() const
+ {
+ return false;
+ }
+ /**
+ Check whether a field type can be partially indexed by a key.
+ @param type field type
+ @retval true Type can have a prefixed key
+ @retval false Type can not have a prefixed key
+ */
+ virtual bool type_can_have_key_part() const
+ {
+ return false;
+ }
+ virtual bool type_can_have_auto_increment_attribute() const
+ {
+ return false;
+ }
+ /**
+ Prepared statement long data:
+ Check whether this parameter data type is compatible with long data.
+ Used to detect whether a long data stream has been supplied to a
+ incompatible data type.
+ */
+ virtual bool is_param_long_data_type() const { return false; }
+ virtual const Type_handler *type_handler_for_comparison() const= 0;
+ virtual const Type_handler *type_handler_for_item_field() const
+ {
+ return this;
+ }
+ virtual const Type_handler *type_handler_for_tmp_table(const Item *) const
+ {
+ return this;
+ }
+ virtual const Type_handler *type_handler_for_union(const Item *) const
+ {
+ return this;
+ }
+ virtual const Type_handler *cast_to_int_type_handler() const
+ {
+ return this;
+ }
+ virtual CHARSET_INFO *charset_for_protocol(const Item *item) const;
virtual const Type_handler*
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
CHARSET_INFO *cs) const
{ return this; }
virtual ~Type_handler() {}
/**
+ Determines MariaDB traditional data types that always present
+ in the server.
+ */
+ virtual bool is_traditional_type() const
+ {
+ return true;
+ }
+ virtual bool is_scalar_type() const { return true; }
+ virtual bool can_return_int() const { return true; }
+ virtual bool can_return_real() const { return true; }
+ virtual bool is_general_purpose_string_type() const { return false; }
+ virtual uint Item_time_precision(Item *item) const;
+ virtual uint Item_datetime_precision(Item *item) const;
+ virtual uint Item_decimal_scale(const Item *item) const;
+ virtual uint Item_decimal_precision(const Item *item) const= 0;
+ /*
+ Returns how many digits a divisor adds into a division result.
+ See Item::divisor_precision_increment() in item.h for more comments.
+ */
+ virtual uint Item_divisor_precision_increment(const Item *) const;
+ /**
Makes a temporary table Field to handle numeric aggregate functions,
e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc.
*/
@@ -86,63 +745,800 @@ public:
virtual Field *make_conversion_table_field(TABLE *TABLE,
uint metadata,
const Field *target) const= 0;
+ virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0;
+ virtual bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ /*
+ This method is called on queries like:
+ CREATE TABLE t2 (a INT) AS SELECT a FROM t1;
+ I.e. column "a" is queried from another table,
+ but its data type is redefined.
+ @param OUT def - The column definition to be redefined
+ @param IN dup - The column definition to take the data type from
+ (i.e. "a INT" in the above example).
+ @param IN file - Table owner handler. If it does not support certain
+ data types, some conversion can be applied.
+ I.g. true BIT to BIT-AS-CHAR.
+ @param IN schema - the owner schema definition, e.g. for the default
+ character set and collation.
+ @retval true - on error
+ @retval false - on success
+ */
+ virtual bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *
+ schema)
+ const;
+ virtual bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const= 0;
+ virtual Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const= 0;
+ Field *make_and_init_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
virtual void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const= 0;
virtual void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const= 0;
+
+ virtual uint32 max_display_length(const Item *item) const= 0;
+ virtual uint32 calc_pack_length(uint32 length) const= 0;
+ virtual bool Item_save_in_value(Item *item, st_value *value) const= 0;
+ virtual bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const= 0;
+ virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0;
+ virtual int Item_save_in_field(Item *item, Field *field,
+ bool no_conversions) const= 0;
+
+ /**
+ Return a string representation of the Item value.
+
+ @param thd thread handle
+ @param str string buffer for representation of the value
+
+ @note
+ If the item has a string result type, the string is escaped
+ according to its character set.
+
+ @retval
+ NULL on error
+ @retval
+ non-NULL a pointer to a a valid string on success
+ */
+ virtual String *print_item_value(THD *thd, Item *item, String *str) const= 0;
+
+ /**
+ Check if
+ WHERE expr=value AND expr=const
+ can be rewritten as:
+ WHERE const=value AND expr=const
+
+ "this" is the comparison handler that is used by "target".
+
+ @param target - the predicate expr=value,
+ whose "expr" argument will be replaced to "const".
+ @param target_expr - the target's "expr" which will be replaced to "const".
+ @param target_value - the target's second argument, it will remain unchanged.
+ @param source - the equality predicate expr=const (or expr<=>const)
+ that can be used to rewrite the "target" part
+ (under certain conditions, see the code).
+ @param source_expr - the source's "expr". It should be exactly equal to
+ the target's "expr" to make condition rewrite possible.
+ @param source_const - the source's "const" argument, it will be inserted
+ into "target" instead of "expr".
+ */
+ virtual bool
+ can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const) const= 0;
+ virtual bool
+ subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const= 0;
+ /**
+ Make a simple constant replacement item for a constant "src",
+ so the new item can futher be used for comparison with "cmp", e.g.:
+ src = cmp -> replacement = cmp
+
+ "this" is the type handler that is used to compare "src" and "cmp".
+
+ @param thd - current thread, for mem_root
+ @param src - The item that we want to replace. It's a const item,
+ but it can be complex enough to calculate on every row.
+ @param cmp - The src's comparand.
+ @retval - a pointer to the created replacement Item
+ @retval - NULL, if could not create a replacement (e.g. on EOM).
+ NULL is also returned for ROWs, because instead of replacing
+ a Item_row to a new Item_row, Type_handler_row just replaces
+ its elements.
+ */
+ virtual Item *make_const_item_for_comparison(THD *thd,
+ Item *src,
+ const Item *cmp) const= 0;
+ virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
+ virtual Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
+ virtual bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items,
+ uint nitems) const= 0;
+ virtual bool Item_func_min_max_fix_attributes(THD *thd,
+ Item_func_min_max *func,
+ Item **items,
+ uint nitems) const;
+ virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
+ virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0;
+ virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0;
+ virtual
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
+
+ virtual longlong Item_val_int_signed_typecast(Item *item) const= 0;
+ virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0;
+
+ virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
+ String *str) const= 0;
+
+ virtual
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const= 0;
+ virtual
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const= 0;
+ virtual
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const= 0;
+ virtual
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const= 0;
+ virtual
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const= 0;
+ virtual
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const= 0;
+ virtual
+ double Item_func_min_max_val_real(Item_func_min_max *) const= 0;
+ virtual
+ longlong Item_func_min_max_val_int(Item_func_min_max *) const= 0;
+ virtual
+ my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
+ my_decimal *) const= 0;
+ virtual
+ bool Item_func_min_max_get_date(Item_func_min_max*,
+ MYSQL_TIME *, ulonglong fuzzydate) const= 0;
+ virtual bool
+ Item_func_between_fix_length_and_dec(Item_func_between *func) const= 0;
+ virtual longlong
+ Item_func_between_val_int(Item_func_between *func) const= 0;
+
+ virtual cmp_item *
+ make_cmp_item(THD *thd, CHARSET_INFO *cs) const= 0;
+
+ virtual in_vector *
+ make_in_vector(THD *thd, const Item_func_in *func, uint nargs) const= 0;
+
+ virtual bool
+ Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *)
+ const= 0;
+
+ virtual bool
+ Item_func_round_fix_length_and_dec(Item_func_round *round) const= 0;
+
+ virtual bool
+ Item_func_int_val_fix_length_and_dec(Item_func_int_val *func) const= 0;
+
+ virtual bool
+ Item_func_abs_fix_length_and_dec(Item_func_abs *func) const= 0;
+
+ virtual bool
+ Item_func_neg_fix_length_and_dec(Item_func_neg *func) const= 0;
+
+ virtual bool
+ Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
+ virtual bool
+ Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
+ virtual bool
+ Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const;
+ virtual bool
+ Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const;
+ virtual bool
+ Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const;
+ virtual bool
+ Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const;
+ virtual bool
+ Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const;
+ virtual bool
+ Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const;
+
+ virtual bool
+ Item_func_plus_fix_length_and_dec(Item_func_plus *func) const= 0;
+ virtual bool
+ Item_func_minus_fix_length_and_dec(Item_func_minus *func) const= 0;
+ virtual bool
+ Item_func_mul_fix_length_and_dec(Item_func_mul *func) const= 0;
+ virtual bool
+ Item_func_div_fix_length_and_dec(Item_func_div *func) const= 0;
+ virtual bool
+ Item_func_mod_fix_length_and_dec(Item_func_mod *func) const= 0;
+};
+
+
+/*
+ Special handler for ROW
+*/
+class Type_handler_row: public Type_handler
+{
+ static const Name m_name_row;
+public:
+ virtual ~Type_handler_row() {}
+ const Name name() const { return m_name_row; }
+ bool is_scalar_type() const { return false; }
+ bool can_return_int() const { return false; }
+ bool can_return_real() const { return false; }
+ enum_field_types field_type() const
+ {
+ DBUG_ASSERT(0);
+ return MYSQL_TYPE_NULL;
+ };
+ Item_result result_type() const
+ {
+ return ROW_RESULT;
+ }
+ Item_result cmp_type() const
+ {
+ return ROW_RESULT;
+ }
+ const Type_handler *type_handler_for_comparison() const;
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+ {
+ DBUG_ASSERT(0);
+ return false;
+ }
+ Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ Field *make_conversion_table_field(TABLE *TABLE,
+ uint metadata,
+ const Field *target) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ bool Column_definition_fix_attributes(Column_definition *c) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ void make_sort_key(uchar *to, Item *item,
+ const SORT_FIELD_ATTR *sort_field,
+ Sort_param *param) const
+ {
+ DBUG_ASSERT(0);
+ }
+ void sortlength(THD *thd, const Type_std_attributes *item,
+ SORT_FIELD_ATTR *attr) const
+ {
+ DBUG_ASSERT(0);
+ }
+ uint32 max_display_length(const Item *item) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ uint32 calc_pack_length(uint32 length) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ uint Item_decimal_precision(const Item *item) const
+ {
+ DBUG_ASSERT(0);
+ return DECIMAL_MAX_PRECISION;
+ }
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const
+ {
+ DBUG_ASSERT(0);
+ return 1;
+ }
+ String *print_item_value(THD *thd, Item *item, String *str) const;
+ bool can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const) const
+ {
+ DBUG_ASSERT(0);
+ return false;
+ }
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ longlong Item_val_int_signed_typecast(Item *item) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ longlong Item_val_int_unsigned_typecast(Item *item) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const
+ {
+ DBUG_ASSERT(0);
+ return 0.0;
+ }
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ double Item_func_min_max_val_real(Item_func_min_max *) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ longlong Item_func_min_max_val_int(Item_func_min_max *) const
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
+ my_decimal *) const
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ bool Item_func_min_max_get_date(Item_func_min_max*,
+ MYSQL_TIME *, ulonglong fuzzydate) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_func_between_fix_length_and_dec(Item_func_between *func) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ longlong Item_func_between_val_int(Item_func_between *func) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const;
+ bool Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *) const;
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+
+ bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+ bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+
+ bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
+ bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
+ bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
+ bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
+ bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
+};
+
+
+/*
+ A common parent class for numeric data type handlers
+*/
+class Type_handler_numeric: public Type_handler
+{
+protected:
+ bool Item_sum_hybrid_fix_length_and_dec_numeric(Item_sum_hybrid *func,
+ const Type_handler *handler)
+ const;
+public:
+ String *print_item_value(THD *thd, Item *item, String *str) const;
+ double Item_func_min_max_val_real(Item_func_min_max *) const;
+ longlong Item_func_min_max_val_int(Item_func_min_max *) const;
+ my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
+ my_decimal *) const;
+ bool Item_func_min_max_get_date(Item_func_min_max*,
+ MYSQL_TIME *, ulonglong fuzzydate) const;
+ virtual ~Type_handler_numeric() { }
+ bool can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const) const;
+ bool Item_func_between_fix_length_and_dec(Item_func_between *func) const;
+ bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const;
};
/*** Abstract classes for every XXX_RESULT */
-class Type_handler_real_result: public Type_handler
+class Type_handler_real_result: public Type_handler_numeric
{
public:
Item_result result_type() const { return REAL_RESULT; }
Item_result cmp_type() const { return REAL_RESULT; }
virtual ~Type_handler_real_result() {}
+ const Type_handler *type_handler_for_comparison() const;
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
+ uint Item_decimal_precision(const Item *item) const;
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+ bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
+ Item **items, uint nitems) const;
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
+ bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
+ String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const;
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const;
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const;
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const;
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const;
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
+ longlong Item_func_between_val_int(Item_func_between *func) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
+ bool Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *) const;
+
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+ bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
+ bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
+ bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
+ bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
+ bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
};
-class Type_handler_decimal_result: public Type_handler
+class Type_handler_decimal_result: public Type_handler_numeric
{
public:
Item_result result_type() const { return DECIMAL_RESULT; }
Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {};
+ const Type_handler *type_handler_for_comparison() const;
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
+ uint32 max_display_length(const Item *item) const;
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
+ uint Item_decimal_precision(const Item *item) const;
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_str(item, protocol, buf);
+ }
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
+ String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const;
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const;
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const;
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const;
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const;
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
+ longlong Item_func_between_val_int(Item_func_between *func) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
+ bool Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *) const;
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+ bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
+ bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
+ bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
+ bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
+ bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
};
-class Type_handler_int_result: public Type_handler
+class Type_handler_int_result: public Type_handler_numeric
{
public:
Item_result result_type() const { return INT_RESULT; }
Item_result cmp_type() const { return INT_RESULT; }
virtual ~Type_handler_int_result() {}
+ const Type_handler *type_handler_for_comparison() const;
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
+ uint Item_decimal_precision(const Item *item) const;
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
+ String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const;
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const;
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const;
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const;
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const;
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
+ longlong Item_func_between_val_int(Item_func_between *func) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
+ bool Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *) const;
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+ bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
+ bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
+ bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
+ bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
+ bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
+};
+
+
+class Type_handler_general_purpose_int: public Type_handler_int_result
+{
+public:
+ bool type_can_have_auto_increment_attribute() const { return true; }
};
class Type_handler_temporal_result: public Type_handler
{
+protected:
+ uint Item_decimal_scale_with_seconds(const Item *item) const;
+ uint Item_divisor_precision_increment_with_seconds(const Item *) const;
public:
Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return TIME_RESULT; }
@@ -152,15 +1548,69 @@ public:
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
+ uint32 max_display_length(const Item *item) const;
+ bool can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const) const;
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
+ String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const;
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const;
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const;
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const;
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const;
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
+ double Item_func_min_max_val_real(Item_func_min_max *) const;
+ longlong Item_func_min_max_val_int(Item_func_min_max *) const;
+ my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
+ my_decimal *) const;
+ bool Item_func_min_max_get_date(Item_func_min_max*,
+ MYSQL_TIME *, ulonglong fuzzydate) const;
+ bool Item_func_between_fix_length_and_dec(Item_func_between *func) const;
+ longlong Item_func_between_val_int(Item_func_between *func) const;
+ bool Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *) const;
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+ bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
+ bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
+ bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
+ bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
+ bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
};
class Type_handler_string_result: public Type_handler
{
+ uint Item_temporal_precision(Item *item, bool is_time) const;
public:
Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return STRING_RESULT; }
+ CHARSET_INFO *charset_for_protocol(const Item *item) const;
virtual ~Type_handler_string_result() {}
+ const Type_handler *type_handler_for_comparison() const;
const Type_handler *
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
CHARSET_INFO *cs) const;
@@ -169,6 +1619,104 @@ public:
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
+ uint32 max_display_length(const Item *item) const;
+ uint Item_time_precision(Item *item) const
+ {
+ return Item_temporal_precision(item, true);
+ }
+ uint Item_datetime_precision(Item *item) const
+ {
+ return Item_temporal_precision(item, false);
+ }
+ uint Item_decimal_precision(const Item *item) const;
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_str(item, protocol, buf);
+ }
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ String *print_item_value(THD *thd, Item *item, String *str) const
+ {
+ return print_item_value_csstr(thd, item, str);
+ }
+ bool can_change_cond_ref_to_const(Item_bool_func2 *target,
+ Item *target_expr, Item *target_value,
+ Item_bool_func2 *source,
+ Item *source_expr, Item *source_const) const;
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const;
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+ bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
+ bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
+ longlong Item_val_int_signed_typecast(Item *item) const;
+ longlong Item_val_int_unsigned_typecast(Item *item) const;
+ String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
+ String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
+ String *) const;
+ double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
+ const;
+ longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
+ const;
+ my_decimal *Item_func_hybrid_field_type_val_decimal(
+ Item_func_hybrid_field_type *,
+ my_decimal *) const;
+ bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ ulonglong fuzzydate) const;
+ String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
+ double Item_func_min_max_val_real(Item_func_min_max *) const;
+ longlong Item_func_min_max_val_int(Item_func_min_max *) const;
+ my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *,
+ my_decimal *) const;
+ bool Item_func_min_max_get_date(Item_func_min_max*,
+ MYSQL_TIME *, ulonglong fuzzydate) const;
+ bool Item_func_between_fix_length_and_dec(Item_func_between *func) const;
+ longlong Item_func_between_val_int(Item_func_between *func) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
+ bool Item_func_in_fix_comparator_compatible_types(THD *thd,
+ Item_func_in *) const;
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+ bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
+ bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
+ bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
+ bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
+ bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
+};
+
+
+class Type_handler_general_purpose_string: public Type_handler_string_result
+{
+public:
+ bool is_general_purpose_string_type() const { return true; }
};
@@ -192,301 +1740,1017 @@ public:
*/
-class Type_handler_tiny: public Type_handler_int_result
+class Type_handler_tiny: public Type_handler_general_purpose_int
{
+ static const Name m_name_tiny;
public:
virtual ~Type_handler_tiny() {}
+ const Name name() const { return m_name_tiny; }
enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
+ uint32 max_display_length(const Item *item) const { return 4; }
+ uint32 calc_pack_length(uint32 length) const { return 1; }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_tiny(item, protocol, buf);
+ }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TINY); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_short: public Type_handler_int_result
+class Type_handler_short: public Type_handler_general_purpose_int
{
+ static const Name m_name_short;
public:
virtual ~Type_handler_short() {}
+ const Name name() const { return m_name_short; }
enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_short(item, protocol, buf);
+ }
+ uint32 max_display_length(const Item *item) const { return 6; }
+ uint32 calc_pack_length(uint32 length) const { return 2; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_SHORT); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_long: public Type_handler_int_result
+class Type_handler_long: public Type_handler_general_purpose_int
{
+ static const Name m_name_int;
public:
virtual ~Type_handler_long() {}
+ const Name name() const { return m_name_int; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
+ uint32 max_display_length(const Item *item) const
+ {
+ return MY_INT32_NUM_DECIMAL_DIGITS;
+ }
+ uint32 calc_pack_length(uint32 length) const { return 4; }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_long(item, protocol, buf);
+ }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_LONG); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_longlong: public Type_handler_int_result
+class Type_handler_longlong: public Type_handler_general_purpose_int
{
+ static const Name m_name_longlong;
public:
virtual ~Type_handler_longlong() {}
+ const Name name() const { return m_name_longlong; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ uint32 max_display_length(const Item *item) const { return 20; }
+ uint32 calc_pack_length(uint32 length) const { return 8; }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_longlong(item, protocol, buf);
+ }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ {
+ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_LONGLONG);
+ }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_int24: public Type_handler_int_result
+class Type_handler_int24: public Type_handler_general_purpose_int
{
+ static const Name m_name_mediumint;
public:
virtual ~Type_handler_int24() {}
+ const Name name() const { return m_name_mediumint; }
enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_long(item, protocol, buf);
+ }
+ uint32 max_display_length(const Item *item) const { return 8; }
+ uint32 calc_pack_length(uint32 length) const { return 3; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_INT24); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
class Type_handler_year: public Type_handler_int_result
{
+ static const Name m_name_year;
public:
virtual ~Type_handler_year() {}
+ const Name name() const { return m_name_year; }
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
+ uint32 max_display_length(const Item *item) const;
+ uint32 calc_pack_length(uint32 length) const { return 1; }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_short(item, protocol, buf);
+ }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_YEAR); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
class Type_handler_bit: public Type_handler_int_result
{
+ static const Name m_name_bit;
public:
virtual ~Type_handler_bit() {}
+ const Name name() const { return m_name_bit; }
enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
+ uint32 max_display_length(const Item *item) const;
+ uint32 calc_pack_length(uint32 length) const { return length / 8; }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_str(item, protocol, buf);
+ }
+ String *print_item_value(THD *thd, Item *item, String *str) const
+ {
+ return print_item_value_csstr(thd, item, str);
+ }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
class Type_handler_float: public Type_handler_real_result
{
+ static const Name m_name_float;
public:
virtual ~Type_handler_float() {}
+ const Name name() const { return m_name_float; }
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
+ bool type_can_have_auto_increment_attribute() const { return true; }
+ uint32 max_display_length(const Item *item) const { return 25; }
+ uint32 calc_pack_length(uint32 length) const { return sizeof(float); }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_float(item, protocol, buf);
+ }
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_real(c, MYSQL_TYPE_FLOAT); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
class Type_handler_double: public Type_handler_real_result
{
+ static const Name m_name_double;
public:
virtual ~Type_handler_double() {}
+ const Name name() const { return m_name_double; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ bool type_can_have_auto_increment_attribute() const { return true; }
+ uint32 max_display_length(const Item *item) const { return 53; }
+ uint32 calc_pack_length(uint32 length) const { return sizeof(double); }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_double(item, protocol, buf);
+ }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_real(c, MYSQL_TYPE_DOUBLE); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_time: public Type_handler_temporal_result
+class Type_handler_time_common: public Type_handler_temporal_result
{
+ static const Name m_name_time;
public:
- virtual ~Type_handler_time() {}
+ virtual ~Type_handler_time_common() { }
+ const Name name() const { return m_name_time; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
+ enum_mysql_timestamp_type mysql_timestamp_type() const
+ {
+ return MYSQL_TIMESTAMP_TIME;
+ }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
+ uint Item_decimal_scale(const Item *item) const
+ {
+ return Item_decimal_scale_with_seconds(item);
+ }
+ uint Item_decimal_precision(const Item *item) const;
+ uint Item_divisor_precision_increment(const Item *item) const
+ {
+ return Item_divisor_precision_increment_with_seconds(item);
+ }
+ const Type_handler *type_handler_for_comparison() const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_time(item, protocol, buf);
+ }
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ String *print_item_value(THD *thd, Item *item, String *str) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
+};
+
+
+class Type_handler_time: public Type_handler_time_common
+{
+ /* number of bytes to store TIME(N) */
+ static uint m_hires_bytes[MAX_DATETIME_PRECISION+1];
+public:
+ static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; }
+ virtual ~Type_handler_time() {}
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_TIME); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_time2: public Type_handler_temporal_result
+class Type_handler_time2: public Type_handler_time_common
{
public:
virtual ~Type_handler_time2() {}
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_TIME2); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_date: public Type_handler_temporal_result
+class Type_handler_temporal_with_date: public Type_handler_temporal_result
{
public:
- virtual ~Type_handler_date() {}
+ virtual ~Type_handler_temporal_with_date() {}
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_date(item, protocol, buf);
+ }
+ int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;
+ bool set_comparator_func(Arg_comparator *cmp) const;
+ cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
+ in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
+};
+
+
+class Type_handler_date_common: public Type_handler_temporal_with_date
+{
+ static const Name m_name_date;
+public:
+ virtual ~Type_handler_date_common() {}
+ const Name name() const { return m_name_date; }
+ const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ enum_mysql_timestamp_type mysql_timestamp_type() const
+ {
+ return MYSQL_TIMESTAMP_DATE;
+ }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ uint Item_decimal_precision(const Item *item) const;
+ String *print_item_value(THD *thd, Item *item, String *str) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+};
+
+class Type_handler_date: public Type_handler_date_common
+{
+public:
+ virtual ~Type_handler_date() {}
+ uint32 calc_pack_length(uint32 length) const { return 4; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATE); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_newdate: public Type_handler_temporal_result
+class Type_handler_newdate: public Type_handler_date_common
{
public:
virtual ~Type_handler_newdate() {}
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; }
+ uint32 calc_pack_length(uint32 length) const { return 3; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_NEWDATE); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_datetime: public Type_handler_temporal_result
+class Type_handler_datetime_common: public Type_handler_temporal_with_date
{
+ static const Name m_name_datetime;
public:
- virtual ~Type_handler_datetime() {}
+ virtual ~Type_handler_datetime_common() {}
+ const Name name() const { return m_name_datetime; }
+ const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ enum_mysql_timestamp_type mysql_timestamp_type() const
+ {
+ return MYSQL_TIMESTAMP_DATETIME;
+ }
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ uint Item_decimal_scale(const Item *item) const
+ {
+ return Item_decimal_scale_with_seconds(item);
+ }
+ uint Item_decimal_precision(const Item *item) const;
+ uint Item_divisor_precision_increment(const Item *item) const
+ {
+ return Item_divisor_precision_increment_with_seconds(item);
+ }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_datetime(item, protocol, buf);
+ }
+ String *print_item_value(THD *thd, Item *item, String *str) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+};
+
+
+class Type_handler_datetime: public Type_handler_datetime_common
+{
+ /* number of bytes to store DATETIME(N) */
+ static uint m_hires_bytes[MAX_DATETIME_PRECISION + 1];
+public:
+ static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; }
+ virtual ~Type_handler_datetime() {}
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATETIME); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_datetime2: public Type_handler_temporal_result
+class Type_handler_datetime2: public Type_handler_datetime_common
{
public:
virtual ~Type_handler_datetime2() {}
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATETIME2); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_timestamp: public Type_handler_temporal_result
+class Type_handler_timestamp_common: public Type_handler_temporal_with_date
{
+ static const Name m_name_timestamp;
public:
- virtual ~Type_handler_timestamp() {}
+ virtual ~Type_handler_timestamp_common() {}
+ const Name name() const { return m_name_timestamp; }
+ const Type_handler *type_handler_for_comparison() const;
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
+ enum_mysql_timestamp_type mysql_timestamp_type() const
+ {
+ return MYSQL_TIMESTAMP_DATETIME;
+ }
+ bool is_timestamp_type() const
+ {
+ return true;
+ }
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ uint Item_decimal_scale(const Item *item) const
+ {
+ return Item_decimal_scale_with_seconds(item);
+ }
+ uint Item_decimal_precision(const Item *item) const;
+ uint Item_divisor_precision_increment(const Item *item) const
+ {
+ return Item_divisor_precision_increment_with_seconds(item);
+ }
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
+ {
+ return Item_send_datetime(item, protocol, buf);
+ }
+ String *print_item_value(THD *thd, Item *item, String *str) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+};
+
+
+class Type_handler_timestamp: public Type_handler_timestamp_common
+{
+ /* number of bytes to store second_part part of the TIMESTAMP(N) */
+ static uint m_sec_part_bytes[MAX_DATETIME_PRECISION + 1];
+public:
+ static uint sec_part_bytes(uint dec) { return m_sec_part_bytes[dec]; }
+ virtual ~Type_handler_timestamp() {}
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TIMESTAMP); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_timestamp2: public Type_handler_temporal_result
+class Type_handler_timestamp2: public Type_handler_timestamp_common
{
public:
virtual ~Type_handler_timestamp2() {}
- enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ {
+ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TIMESTAMP2);
+ }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
class Type_handler_olddecimal: public Type_handler_decimal_result
{
+ static const Name m_name_decimal;
public:
virtual ~Type_handler_olddecimal() {}
+ const Name name() const { return m_name_decimal; }
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
+ uint32 calc_pack_length(uint32 length) const { return length; }
+ const Type_handler *type_handler_for_tmp_table(const Item *item) const;
+ const Type_handler *type_handler_for_union(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_DECIMAL); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
class Type_handler_newdecimal: public Type_handler_decimal_result
{
+ static const Name m_name_decimal;
public:
virtual ~Type_handler_newdecimal() {}
+ const Name name() const { return m_name_decimal; }
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_null: public Type_handler_string_result
+class Type_handler_null: public Type_handler_general_purpose_string
{
+ static const Name m_name_null;
public:
virtual ~Type_handler_null() {}
+ const Name name() const { return m_name_null; }
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
+ const Type_handler *type_handler_for_comparison() const;
+ const Type_handler *type_handler_for_tmp_table(const Item *item) const;
+ const Type_handler *type_handler_for_union(const Item *) const;
+ uint32 max_display_length(const Item *item) const { return 0; }
+ uint32 calc_pack_length(uint32 length) const { return 0; }
+ bool Item_save_in_value(Item *item, st_value *value) const;
+ bool Item_send(Item *item, Protocol *protocol, st_value *buf) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_NULL); }
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_string: public Type_handler_string_result
+class Type_handler_longstr: public Type_handler_general_purpose_string
{
public:
+ bool type_can_have_key_part() const
+ {
+ return true;
+ }
+};
+
+
+class Type_handler_string: public Type_handler_longstr
+{
+ static const Name m_name_char;
+public:
virtual ~Type_handler_string() {}
+ const Name name() const { return m_name_char; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ bool is_param_long_data_type() const { return true; }
+ uint32 calc_pack_length(uint32 length) const { return length; }
+ const Type_handler *type_handler_for_tmp_table(const Item *item) const
+ {
+ return varstring_type_handler(item);
+ }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
+};
+
+
+/* Old varchar */
+class Type_handler_var_string: public Type_handler_string
+{
+ static const Name m_name_var_string;
+public:
+ virtual ~Type_handler_var_string() {}
+ const Name name() const { return m_name_var_string; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VAR_STRING; }
+ enum_field_types real_field_type() const { return MYSQL_TYPE_STRING; }
+ const Type_handler *type_handler_for_tmp_table(const Item *item) const
+ {
+ return varstring_type_handler(item);
+ }
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const
+ { return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_STRING); }
+ const Type_handler *type_handler_for_union(const Item *item) const
+ {
+ return varstring_type_handler(item);
+ }
};
-class Type_handler_varchar: public Type_handler_string_result
+class Type_handler_varchar: public Type_handler_longstr
{
+ static const Name m_name_varchar;
public:
virtual ~Type_handler_varchar() {}
+ const Name name() const { return m_name_varchar; }
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ uint32 calc_pack_length(uint32 length) const
+ {
+ return (length + (length < 256 ? 1: 2));
+ }
+ const Type_handler *type_handler_for_tmp_table(const Item *item) const
+ {
+ return varstring_type_handler(item);
+ }
+ const Type_handler *type_handler_for_union(const Item *item) const
+ {
+ return varstring_type_handler(item);
+ }
+ bool is_param_long_data_type() const { return true; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
+};
+
+
+class Type_handler_blob_common: public Type_handler_longstr
+{
+public:
+ virtual ~Type_handler_blob_common() { }
+ const Type_handler *type_handler_for_tmp_table(const Item *item) const
+ {
+ return blob_type_handler(item);
+ }
+ const Type_handler *type_handler_for_union(const Item *item) const
+ {
+ return blob_type_handler(item);
+ }
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+ {
+ return false; // Materialization does not work with BLOB columns
+ }
+ bool is_param_long_data_type() const { return true; }
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
};
-class Type_handler_tiny_blob: public Type_handler_string_result
+class Type_handler_tiny_blob: public Type_handler_blob_common
{
+ static const Name m_name_tinyblob;
public:
virtual ~Type_handler_tiny_blob() {}
+ const Name name() const { return m_name_tinyblob; }
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_medium_blob: public Type_handler_string_result
+class Type_handler_medium_blob: public Type_handler_blob_common
{
+ static const Name m_name_mediumblob;
public:
virtual ~Type_handler_medium_blob() {}
+ const Name name() const { return m_name_mediumblob; }
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_long_blob: public Type_handler_string_result
+class Type_handler_long_blob: public Type_handler_blob_common
{
+ static const Name m_name_longblob;
public:
virtual ~Type_handler_long_blob() {}
+ const Name name() const { return m_name_longblob; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
+ uint32 calc_pack_length(uint32 length) const;
+ Item *create_typecast_item(THD *thd, Item *item,
+ const Type_cast_attributes &attr) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_blob: public Type_handler_string_result
+class Type_handler_blob: public Type_handler_blob_common
{
+ static const Name m_name_blob;
public:
virtual ~Type_handler_blob() {}
+ const Name name() const { return m_name_blob; }
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
#ifdef HAVE_SPATIAL
class Type_handler_geometry: public Type_handler_string_result
{
+ static const Name m_name_geometry;
public:
virtual ~Type_handler_geometry() {}
+ const Name name() const { return m_name_geometry; }
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
+ bool is_param_long_data_type() const { return true; }
+ uint32 calc_pack_length(uint32 length) const;
+ const Type_handler *type_handler_for_comparison() const;
+ bool type_can_have_key_part() const
+ {
+ return true;
+ }
+ bool subquery_type_allows_materialization(const Item *inner,
+ const Item *outer) const
+ {
+ return false; // Materialization does not work with GEOMETRY columns
+ }
+ bool Item_param_set_from_value(THD *thd,
+ Item_param *param,
+ const Type_all_attributes *attr,
+ const st_value *value) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
+
+ bool can_return_int() const { return false; }
+ bool can_return_real() const { return false; }
+ bool is_traditional_type() const
+ {
+ return false;
+ }
+ bool Item_func_round_fix_length_and_dec(Item_func_round *) const;
+ bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
+ bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
+ bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *h,
+ Type_all_attributes *attr,
+ Item **items, uint nitems) const;
+ bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
+ bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
+ bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
+
+ bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const;
+ bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const;
+ bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const;
+ bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const;
+ bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const;
+ bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const;
+ bool Item_date_typecast_fix_length_and_dec(Item_date_typecast *) const;
+ bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const;
};
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry;
#endif
-class Type_handler_enum: public Type_handler_string_result
+class Type_handler_typelib: public Type_handler_general_purpose_string
+{
+public:
+ virtual ~Type_handler_typelib() { }
+ enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ const Type_handler *type_handler_for_item_field() const;
+ const Type_handler *cast_to_int_type_handler() const;
+ bool Item_hybrid_func_fix_attributes(THD *thd,
+ const char *name,
+ Type_handler_hybrid_field_type *,
+ Type_all_attributes *atrr,
+ Item **items, uint nitems) const;
+ bool Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ bool Column_definition_redefine_stage1(Column_definition *def,
+ const Column_definition *dup,
+ const handler *file,
+ const Schema_specification_st *schema)
+ const;
+};
+
+
+class Type_handler_enum: public Type_handler_typelib
{
+ static const Name m_name_enum;
public:
virtual ~Type_handler_enum() {}
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Name name() const { return m_name_enum; }
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
-class Type_handler_set: public Type_handler_string_result
+class Type_handler_set: public Type_handler_typelib
{
+ static const Name m_name_set;
public:
virtual ~Type_handler_set() {}
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Name name() const { return m_name_set; }
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
+ uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ bool Column_definition_fix_attributes(Column_definition *c) const;
+ bool Column_definition_prepare_stage2(Column_definition *c,
+ handler *file,
+ ulonglong table_flags) const;
+ Field *make_table_field(const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Type_all_attributes &attr,
+ TABLE *table) const;
};
@@ -499,97 +2763,192 @@ public:
Makes sure that field_type(), cmp_type() and result_type()
are always in sync to each other for hybrid functions.
*/
-class Type_handler_hybrid_field_type: public Type_handler
+class Type_handler_hybrid_field_type
{
const Type_handler *m_type_handler;
- const Type_handler *get_handler_by_result_type(Item_result type) const;
+ bool aggregate_for_min_max(const Type_handler *other);
public:
Type_handler_hybrid_field_type();
Type_handler_hybrid_field_type(const Type_handler *handler)
:m_type_handler(handler)
{ }
- Type_handler_hybrid_field_type(enum_field_types type)
- :m_type_handler(get_handler_by_field_type(type))
- { }
Type_handler_hybrid_field_type(const Type_handler_hybrid_field_type *other)
:m_type_handler(other->m_type_handler)
{ }
- enum_field_types field_type() const { return m_type_handler->field_type(); }
+ const Type_handler *type_handler() const { return m_type_handler; }
enum_field_types real_field_type() const
{
return m_type_handler->real_field_type();
}
- Item_result result_type() const { return m_type_handler->result_type(); }
Item_result cmp_type() const { return m_type_handler->cmp_type(); }
+ enum_mysql_timestamp_type mysql_timestamp_type() const
+ {
+ return m_type_handler->mysql_timestamp_type();
+ }
+ bool is_timestamp_type() const
+ {
+ return m_type_handler->is_timestamp_type();
+ }
void set_handler(const Type_handler *other)
{
m_type_handler= other;
}
const Type_handler *set_handler_by_result_type(Item_result type)
{
- return (m_type_handler= get_handler_by_result_type(type));
+ return (m_type_handler= Type_handler::get_handler_by_result_type(type));
+ }
+ const Type_handler *set_handler_by_cmp_type(Item_result type)
+ {
+ return (m_type_handler= Type_handler::get_handler_by_cmp_type(type));
}
const Type_handler *set_handler_by_result_type(Item_result type,
uint max_octet_length,
CHARSET_INFO *cs)
{
- m_type_handler= get_handler_by_result_type(type);
+ m_type_handler= Type_handler::get_handler_by_result_type(type);
return m_type_handler=
m_type_handler->type_handler_adjusted_to_max_octet_length(max_octet_length,
cs);
}
const Type_handler *set_handler_by_field_type(enum_field_types type)
{
- return (m_type_handler= get_handler_by_field_type(type));
+ return (m_type_handler= Type_handler::get_handler_by_field_type(type));
}
const Type_handler *set_handler_by_real_type(enum_field_types type)
{
- return (m_type_handler= get_handler_by_real_type(type));
- }
- const Type_handler *
- type_handler_adjusted_to_max_octet_length(uint max_octet_length,
- CHARSET_INFO *cs) const
- {
- return
- m_type_handler->type_handler_adjusted_to_max_octet_length(max_octet_length,
- cs);
- }
- Field *make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
- const Item *item) const
- {
- return m_type_handler->make_num_distinct_aggregator_field(mem_root, item);
+ return (m_type_handler= Type_handler::get_handler_by_real_type(type));
}
- Field *make_conversion_table_field(TABLE *table, uint metadata,
- const Field *target) const
+ bool aggregate_for_comparison(const Type_handler *other);
+ bool aggregate_for_comparison(const char *funcname,
+ Item **items, uint nitems,
+ bool treat_int_to_uint_as_decimal);
+ bool aggregate_for_result(const Type_handler *other);
+ bool aggregate_for_result(const char *funcname,
+ Item **item, uint nitems, bool treat_bit_as_number);
+ bool aggregate_for_min_max(const char *funcname, Item **item, uint nitems);
+
+ bool aggregate_for_num_op(const class Type_aggregator *aggregator,
+ const Type_handler *h0, const Type_handler *h1);
+};
+
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_row type_handler_row;
+extern MYSQL_PLUGIN_IMPORT Type_handler_null type_handler_null;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_float type_handler_float;
+extern MYSQL_PLUGIN_IMPORT Type_handler_double type_handler_double;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_bit type_handler_bit;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_enum type_handler_enum;
+extern MYSQL_PLUGIN_IMPORT Type_handler_set type_handler_set;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_string type_handler_string;
+extern MYSQL_PLUGIN_IMPORT Type_handler_var_string type_handler_var_string;
+extern MYSQL_PLUGIN_IMPORT Type_handler_varchar type_handler_varchar;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_tiny type_handler_tiny;
+extern MYSQL_PLUGIN_IMPORT Type_handler_short type_handler_short;
+extern MYSQL_PLUGIN_IMPORT Type_handler_int24 type_handler_int24;
+extern MYSQL_PLUGIN_IMPORT Type_handler_long type_handler_long;
+extern MYSQL_PLUGIN_IMPORT Type_handler_longlong type_handler_longlong;
+extern MYSQL_PLUGIN_IMPORT Type_handler_longlong type_handler_ulonglong;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_newdecimal type_handler_newdecimal;
+extern MYSQL_PLUGIN_IMPORT Type_handler_olddecimal type_handler_olddecimal;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_year type_handler_year;
+extern MYSQL_PLUGIN_IMPORT Type_handler_newdate type_handler_newdate;
+extern MYSQL_PLUGIN_IMPORT Type_handler_date type_handler_date;
+extern MYSQL_PLUGIN_IMPORT Type_handler_time type_handler_time;
+extern MYSQL_PLUGIN_IMPORT Type_handler_time2 type_handler_time2;
+extern MYSQL_PLUGIN_IMPORT Type_handler_datetime type_handler_datetime;
+extern MYSQL_PLUGIN_IMPORT Type_handler_datetime2 type_handler_datetime2;
+extern MYSQL_PLUGIN_IMPORT Type_handler_timestamp type_handler_timestamp;
+extern MYSQL_PLUGIN_IMPORT Type_handler_timestamp2 type_handler_timestamp2;
+
+extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob;
+
+class Type_aggregator
+{
+ bool m_is_commutative;
+ class Pair
{
- return m_type_handler->make_conversion_table_field(table, metadata, target);
- }
- void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
- Sort_param *param) const
+ public:
+ const Type_handler *m_handler1;
+ const Type_handler *m_handler2;
+ const Type_handler *m_result;
+ Pair() { }
+ Pair(const Type_handler *handler1,
+ const Type_handler *handler2,
+ const Type_handler *result)
+ :m_handler1(handler1), m_handler2(handler2), m_result(result)
+ { }
+ bool eq(const Type_handler *handler1, const Type_handler *handler2) const
+ {
+ return m_handler1 == handler1 && m_handler2 == handler2;
+ }
+ };
+ Dynamic_array<Pair> m_array;
+ const Pair* find_pair(const Type_handler *handler1,
+ const Type_handler *handler2) const;
+public:
+ Type_aggregator(bool is_commutative= false)
+ :m_is_commutative(is_commutative)
+ { }
+ bool add(const Type_handler *handler1,
+ const Type_handler *handler2,
+ const Type_handler *result)
{
- m_type_handler->make_sort_key(to, item, sort_field, param);
+ return m_array.append(Pair(handler1, handler2, result));
}
- void sortlength(THD *thd,
- const Type_std_attributes *item,
- SORT_FIELD_ATTR *attr) const
+ const Type_handler *find_handler(const Type_handler *handler1,
+ const Type_handler *handler2) const
{
- m_type_handler->sortlength(thd, item, attr);
+ const Pair* el= find_pair(handler1, handler2);
+ return el ? el->m_result : NULL;
}
-
+ bool is_commutative() const { return m_is_commutative; }
};
-/**
- This class is used for Item_type_holder, which preserves real_type.
-*/
-class Type_handler_hybrid_real_field_type:
- public Type_handler_hybrid_field_type
+class Type_aggregator_commutative: public Type_aggregator
{
public:
- Type_handler_hybrid_real_field_type(enum_field_types type)
- :Type_handler_hybrid_field_type(get_handler_by_real_type(type))
+ Type_aggregator_commutative()
+ :Type_aggregator(true)
{ }
};
+class Type_handler_data
+{
+public:
+ Type_aggregator_commutative m_type_aggregator_for_result;
+ Type_aggregator_commutative m_type_aggregator_for_comparison;
+
+ Type_aggregator_commutative m_type_aggregator_for_plus;
+ Type_aggregator_commutative m_type_aggregator_for_mul;
+
+ Type_aggregator m_type_aggregator_for_minus;
+ Type_aggregator m_type_aggregator_for_div;
+ Type_aggregator m_type_aggregator_for_mod;
+#ifndef DBUG_OFF
+ // This is used for mtr purposes in debug builds
+ Type_aggregator m_type_aggregator_non_commutative_test;
+#endif
+ bool init();
+};
+
+
+extern Type_handler_data *type_handler_data;
+
#endif /* SQL_TYPE_H_INCLUDED */
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 05698ce82cc..612cc97f6a2 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -54,12 +54,12 @@ static HASH udf_hash;
static mysql_rwlock_t THR_LOCK_udf;
-static udf_func *add_udf(LEX_STRING *name, Item_result ret,
- char *dl, Item_udftype typ);
+static udf_func *add_udf(LEX_CSTRING *name, Item_result ret,
+ const char *dl, Item_udftype typ);
static void del_udf(udf_func *udf);
static void *find_udf_dl(const char *dl);
-static char *init_syms(udf_func *tmp, char *nm)
+static const char *init_syms(udf_func *tmp, char *nm)
{
char *end;
@@ -192,7 +192,7 @@ void udf_init()
while (!(error= read_record_info.read_record(&read_record_info)))
{
DBUG_PRINT("info",("init udf record"));
- LEX_STRING name;
+ LEX_CSTRING name;
name.str=get_field(&mem, table->field[0]);
name.length = (uint) strlen(name.str);
char *dl_name= get_field(&mem, table->field[2]);
@@ -242,7 +242,8 @@ void udf_init()
}
tmp->dlhandle = dl;
{
- char buf[SAFE_NAME_LEN+16], *missing;
+ char buf[SAFE_NAME_LEN+16];
+ const char *missing;
if ((missing= init_syms(tmp, buf)))
{
sql_print_error(ER_THD(new_thd, ER_CANT_FIND_DL_ENTRY), missing);
@@ -311,9 +312,9 @@ static void del_udf(udf_func *udf)
The functions will be automaticly removed when the least threads
doesn't use it anymore
*/
- char *name= udf->name.str;
+ const char *name= udf->name.str;
uint name_length=udf->name.length;
- udf->name.str=(char*) "*";
+ udf->name.str= "*";
udf->name.length=1;
my_hash_update(&udf_hash,(uchar*) udf,(uchar*) name,name_length);
}
@@ -351,6 +352,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
{
udf_func *udf=0;
DBUG_ENTER("find_udf");
+ DBUG_ASSERT(strlen(name) == length);
if (!initialized)
DBUG_RETURN(NULL);
@@ -362,8 +364,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
else
mysql_rwlock_rdlock(&THR_LOCK_udf); /* Called during parsing */
- if ((udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) name,
- length ? length : (uint) strlen(name))))
+ if ((udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) name, length)))
{
if (!udf->dlhandle)
udf=0; // Could not be opened
@@ -395,7 +396,7 @@ static void *find_udf_dl(const char *dl)
/* Assume that name && dl is already allocated */
-static udf_func *add_udf(LEX_STRING *name, Item_result ret, char *dl,
+static udf_func *add_udf(LEX_CSTRING *name, Item_result ret, const char *dl,
Item_udftype type)
{
if (!name || !dl || !(uint) type || (uint) type > (uint) UDFTYPE_AGGREGATE)
@@ -431,7 +432,7 @@ static int mysql_drop_function_internal(THD *thd, udf_func *udf, TABLE *table)
{
DBUG_ENTER("mysql_drop_function_internal");
- char *exact_name_str= udf->name.str;
+ const char *exact_name_str= udf->name.str;
uint exact_name_len= udf->name.length;
del_udf(udf);
@@ -548,7 +549,8 @@ int mysql_create_function(THD *thd,udf_func *udf)
}
udf->dlhandle=dl;
{
- char buf[SAFE_NAME_LEN+16], *missing;
+ char buf[SAFE_NAME_LEN+16];
+ const char *missing;
if ((missing= init_syms(udf, buf)))
{
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), missing);
@@ -604,7 +606,7 @@ err:
}
-int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
+int mysql_drop_function(THD *thd, const LEX_CSTRING *udf_name)
{
TABLE *table;
TABLE_LIST tables;
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index d3ec1cc1f95..1c805227f97 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -37,10 +37,10 @@ typedef longlong (*Udf_func_longlong)(UDF_INIT *, UDF_ARGS *, uchar *,
typedef struct st_udf_func
{
- LEX_STRING name;
+ LEX_CSTRING name;
Item_result returns;
Item_udftype type;
- char *dl;
+ const char *dl;
void *dlhandle;
Udf_func_any func;
Udf_func_init func_init;
@@ -137,10 +137,10 @@ class udf_handler :public Sql_alloc
#ifdef HAVE_DLOPEN
void udf_init(void),udf_free(void);
-udf_func *find_udf(const char *name, uint len=0,bool mark_used=0);
+udf_func *find_udf(const char *name, uint len, bool mark_used=0);
void free_udf(udf_func *udf);
int mysql_create_function(THD *thd,udf_func *udf);
-int mysql_drop_function(THD *thd,const LEX_STRING *name);
+int mysql_drop_function(THD *thd, const LEX_CSTRING *name);
#else
static inline void udf_init(void) { }
static inline void udf_free(void) { }
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 92923779be7..996fe8ade11 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -48,15 +48,67 @@ bool mysql_union(THD *thd, LEX *lex, select_result *result,
** store records in temporary table for UNION
***************************************************************************/
-int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
+int select_unit::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
return 0;
}
+/**
+ This called by SELECT_LEX_UNIT::exec when select changed
+*/
-int select_union::send_data(List<Item> &values)
+void select_unit::change_select()
{
+ uint current_select_number= thd->lex->current_select->select_number;
+ DBUG_ENTER("select_unit::change_select");
+ DBUG_PRINT("enter", ("select in unit change: %u -> %u",
+ curr_sel, current_select_number));
+ DBUG_ASSERT(curr_sel != current_select_number);
+ curr_sel= current_select_number;
+ /* New SELECT processing starts */
+ DBUG_ASSERT(table->file->inited == 0);
+ switch (thd->lex->current_select->linkage)
+ {
+ case INTERSECT_TYPE:
+ intersect_mark->value= prev_step= curr_step;
+ curr_step= current_select_number;
+ case EXCEPT_TYPE:
+ step= thd->lex->current_select->linkage;
+ break;
+ default:
+ step= UNION_TYPE;
+ break;
+ }
+ DBUG_VOID_RETURN;
+}
+/**
+ Fill temporary tables for UNION/EXCEPT/INTERSECT
+
+ @Note
+UNION:
+ just add records to the table (with 'counter' field first if INTERSECT
+ present in the sequence).
+EXCEPT:
+ looks for the record in the table (with 'counter' field first if
+ INTERSECT present in the sequence) and delete it if found
+INTESECT:
+ looks for the same record with 'counter' field of previous operation,
+ put as a 'counter' number of the current SELECT.
+ We scan the table and remove all records which marked with not last
+ 'counter' after processing all records in send_eof and only if it last
+ SELECT of sequence of INTERSECTS.
+
+ @param values List of record items to process.
+
+ @retval 0 - OK
+ @retval -1 - duplicate
+ @retval 1 - error
+*/
+int select_unit::send_data(List<Item> &values)
+{
+ int rc;
+ int not_reported_error= 0;
if (unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
@@ -66,44 +118,189 @@ int select_union::send_data(List<Item> &values)
return 0;
if (table->no_rows_with_nulls)
table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT;
- fill_record(thd, table, table->field, values, TRUE, FALSE);
+ if (intersect_mark)
+ {
+ fill_record(thd, table, table->field + 1, values, TRUE, FALSE);
+ table->field[0]->store((ulonglong) curr_step, 1);
+ }
+ else
+ fill_record(thd, table, table->field, values, TRUE, FALSE);
if (thd->is_error())
- return 1;
+ {
+ rc= 1;
+ goto end;
+ }
if (table->no_rows_with_nulls)
{
table->null_catch_flags&= ~CHECK_ROW_FOR_NULLS_TO_REJECT;
if (table->null_catch_flags)
- return 0;
+ {
+ rc= 0;
+ goto end;
+ }
}
- if ((write_err= table->file->ha_write_tmp_row(table->record[0])))
+ // select_unit::change_select() change step & Co correctly for each SELECT
+ switch (step)
{
- if (write_err == HA_ERR_FOUND_DUPP_KEY)
+ case UNION_TYPE:
+ {
+ if ((write_err= table->file->ha_write_tmp_row(table->record[0])))
+ {
+ if (write_err == HA_ERR_FOUND_DUPP_KEY)
+ {
+ /*
+ Inform upper level that we found a duplicate key, that should not
+ be counted as part of limit
+ */
+ rc= -1;
+ goto end;
+ }
+ bool is_duplicate= FALSE;
+ /* create_internal_tmp_table_from_heap will generate error if needed */
+ if (table->file->is_fatal_error(write_err, HA_CHECK_DUP) &&
+ create_internal_tmp_table_from_heap(thd, table,
+ tmp_table_param.start_recinfo,
+ &tmp_table_param.recinfo,
+ write_err, 1, &is_duplicate))
+ {
+ rc= 1;
+ goto end;
+ }
+
+ if (is_duplicate)
+ {
+ rc= -1;
+ goto end;
+ }
+ }
+ break;
+ }
+ case EXCEPT_TYPE:
{
+ int find_res;
/*
- Inform upper level that we found a duplicate key, that should not
- be counted as part of limit
+ The temporary table uses very first index or constrain for
+ checking unique constrain.
*/
- return -1;
+ if (!(find_res= table->file->find_unique_row(table->record[0], 0)))
+ {
+ DBUG_ASSERT(!table->triggers);
+ table->status|= STATUS_DELETED;
+ not_reported_error= table->file->ha_delete_tmp_row(table->record[0]);
+ rc= MY_TEST(not_reported_error);
+ goto end;
+ }
+ else
+ {
+ if ((rc= not_reported_error= (find_res != 1)))
+ goto end;
+ }
+ break;
+ }
+ case INTERSECT_TYPE:
+ {
+ int find_res;
+ /*
+ The temporary table uses very first index or constrain for
+ checking unique constrain.
+ */
+ if (!(find_res= table->file->find_unique_row(table->record[0], 0)))
+ {
+ DBUG_ASSERT(!table->triggers);
+ if (table->field[0]->val_int() != prev_step)
+ {
+ rc= 0;
+ goto end;
+ }
+ store_record(table, record[1]);
+ table->field[0]->store(curr_step, 0);
+ not_reported_error= table->file->ha_update_tmp_row(table->record[1],
+ table->record[0]);
+ rc= MY_TEST(not_reported_error);
+ DBUG_ASSERT(rc != HA_ERR_RECORD_IS_THE_SAME);
+ goto end;
+ }
+ else
+ {
+ if ((rc= not_reported_error= (find_res != 1)))
+ goto end;
+ }
+ break;
}
- bool is_duplicate= FALSE;
- /* create_internal_tmp_table_from_heap will generate error if needed */
- if (table->file->is_fatal_error(write_err, HA_CHECK_DUP) &&
- create_internal_tmp_table_from_heap(thd, table,
- tmp_table_param.start_recinfo,
- &tmp_table_param.recinfo,
- write_err, 1, &is_duplicate))
- return 1;
- if (is_duplicate)
- return -1;
+ default:
+ DBUG_ASSERT(0);
}
- return 0;
+ rc= 0;
+
+end:
+ if (not_reported_error)
+ {
+ DBUG_ASSERT(rc);
+ table->file->print_error(not_reported_error, MYF(0));
+ }
+ return rc;
+}
+
+bool select_unit::send_eof()
+{
+ if (step != INTERSECT_TYPE ||
+ (thd->lex->current_select->next_select() &&
+ thd->lex->current_select->next_select()->linkage == INTERSECT_TYPE))
+ {
+ /*
+ it is not INTESECT or next SELECT in the sequence is INTERSECT so no
+ need filtering (the last INTERSECT in this sequence of intersects will
+ filter).
+ */
+ return 0;
+ }
+
+ /*
+ It is last select in the sequence of INTERSECTs so we should filter out
+ all records except marked with actual counter.
+
+ TODO: as optimization for simple case this could be moved to
+ 'fake_select' WHERE condition
+ */
+ handler *file= table->file;
+ int error;
+
+ if (file->ha_rnd_init_with_error(1))
+ return 1;
+
+ do
+ {
+ error= file->ha_rnd_next(table->record[0]);
+ if (error)
+ {
+ if (error == HA_ERR_END_OF_FILE)
+ {
+ error= 0;
+ break;
+ }
+ if (unlikely(error == HA_ERR_RECORD_DELETED))
+ {
+ error= 0;
+ continue;
+ }
+ break;
+ }
+ if (table->field[0]->val_int() != curr_step)
+ error= file->ha_delete_tmp_row(table->record[0]);
+ } while (!error);
+ file->ha_rnd_end();
+
+ if (error)
+ table->file->print_error(error, MYF(0));
+
+ return(MY_TEST(error));
}
int select_union_recursive::send_data(List<Item> &values)
{
- int rc= select_union::send_data(values);
+ int rc= select_unit::send_data(values);
if (write_err != HA_ERR_FOUND_DUPP_KEY &&
write_err != HA_ERR_FOUND_DUPP_UNIQUE)
@@ -123,13 +320,7 @@ int select_union_recursive::send_data(List<Item> &values)
}
-bool select_union::send_eof()
-{
- return 0;
-}
-
-
-bool select_union::flush()
+bool select_unit::flush()
{
int error;
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
@@ -140,11 +331,12 @@ bool select_union::flush()
return 0;
}
+
/*
Create a temporary table to store the result of select_union.
SYNOPSIS
- select_union::create_result_table()
+ select_unit::create_result_table()
thd thread handle
column_types a list of items used to define columns of the
temporary table
@@ -155,6 +347,7 @@ bool select_union::flush()
bit_fields_as_long convert bit fields to ulonglong
create_table whether to physically create result table
keep_row_order keep rows in order as they were inserted
+ hidden number of hidden fields (for INTERSECT)
DESCRIPTION
Create a temporary table that is used to store the result of a UNION,
@@ -166,16 +359,18 @@ bool select_union::flush()
*/
bool
-select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
+select_unit::create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long, bool create_table,
- bool keep_row_order)
+ bool keep_row_order,
+ uint hidden)
{
DBUG_ASSERT(table == 0);
tmp_table_param.init();
tmp_table_param.field_count= column_types->elements;
tmp_table_param.bit_fields_as_long= bit_fields_as_long;
+ tmp_table_param.hidden_field_count= hidden;
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
@@ -203,12 +398,14 @@ select_union_recursive::create_result_table(THD *thd_arg,
const char *alias,
bool bit_fields_as_long,
bool create_table,
- bool keep_row_order)
+ bool keep_row_order,
+ uint hidden)
{
- if (select_union::create_result_table(thd_arg, column_types,
- is_union_distinct, options,
- "", bit_fields_as_long,
- create_table, keep_row_order))
+ if (select_unit::create_result_table(thd_arg, column_types,
+ is_union_distinct, options,
+ "", bit_fields_as_long,
+ create_table, keep_row_order,
+ hidden))
return true;
if (! (incr_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
@@ -253,7 +450,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
tables of JOIN - exec_tmp_table_[1 | 2].
*/
-void select_union::cleanup()
+void select_unit::cleanup()
{
table->file->extra(HA_EXTRA_RESET_STATE);
table->file->ha_delete_all_rows();
@@ -264,7 +461,7 @@ void select_union_recursive::cleanup()
{
if (table)
{
- select_union::cleanup();
+ select_unit::cleanup();
free_tmp_table(thd, table);
}
@@ -440,6 +637,232 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg,
}
+bool st_select_lex_unit::prepare_join(THD *thd_arg, SELECT_LEX *sl,
+ select_result *tmp_result,
+ ulong additional_options,
+ bool is_union_select)
+{
+ DBUG_ENTER("st_select_lex_unit::prepare_join");
+ bool can_skip_order_by;
+ sl->options|= SELECT_NO_UNLOCK;
+ JOIN *join= new JOIN(thd_arg, sl->item_list,
+ (sl->options | thd_arg->variables.option_bits |
+ additional_options),
+ tmp_result);
+ if (!join)
+ DBUG_RETURN(true);
+
+ thd_arg->lex->current_select= sl;
+
+ can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
+
+ saved_error= join->prepare(sl->table_list.first,
+ sl->with_wild,
+ sl->where,
+ (can_skip_order_by ? 0 :
+ sl->order_list.elements) +
+ sl->group_list.elements,
+ can_skip_order_by ?
+ NULL : sl->order_list.first,
+ can_skip_order_by,
+ sl->group_list.first,
+ sl->having,
+ (is_union_select ? NULL :
+ thd_arg->lex->proc_list.first),
+ sl, this);
+
+ /* There are no * in the statement anymore (for PS) */
+ sl->with_wild= 0;
+ last_procedure= join->procedure;
+
+ if (saved_error || (saved_error= thd_arg->is_fatal_error))
+ DBUG_RETURN(true);
+ /*
+ Remove all references from the select_lex_units to the subqueries that
+ are inside the ORDER BY clause.
+ */
+ if (can_skip_order_by)
+ {
+ for (ORDER *ord= (ORDER *)sl->order_list.first; ord; ord= ord->next)
+ {
+ (*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+class Type_holder: public Sql_alloc,
+ public Item_args,
+ public Type_handler_hybrid_field_type,
+ public Type_all_attributes,
+ public Type_geometry_attributes
+{
+ TYPELIB *m_typelib;
+ bool m_maybe_null;
+public:
+ Type_holder()
+ :m_typelib(NULL),
+ m_maybe_null(false)
+ { }
+
+ void set_maybe_null(bool maybe_null_arg) { m_maybe_null= maybe_null_arg; }
+ bool get_maybe_null() const { return m_maybe_null; }
+
+ uint decimal_precision() const
+ {
+ /*
+ Type_holder is not used directly to create fields, so
+ its virtual decimal_precision() is never called.
+ We should eventually extend create_result_table() to accept
+ an array of Type_holders directly, without having to allocate
+ Item_type_holder's and put them into List<Item>.
+ */
+ DBUG_ASSERT(0);
+ return 0;
+ }
+ void set_geometry_type(uint type)
+ {
+ Type_geometry_attributes::set_geometry_type(type);
+ }
+ uint uint_geometry_type() const
+ {
+ return Type_geometry_attributes::get_geometry_type();
+ }
+ void set_typelib(TYPELIB *typelib)
+ {
+ m_typelib= typelib;
+ }
+ TYPELIB *get_typelib() const
+ {
+ return m_typelib;
+ }
+
+ bool aggregate_attributes(THD *thd)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ m_maybe_null|= args[i]->maybe_null;
+ return
+ type_handler()->Item_hybrid_func_fix_attributes(thd,
+ "UNION", this, this,
+ args, arg_count);
+ }
+};
+
+
+/**
+ Aggregate data type handlers for the "count" leftmost UNION parts.
+*/
+bool st_select_lex_unit::join_union_type_handlers(THD *thd_arg,
+ Type_holder *holders,
+ uint count)
+{
+ DBUG_ENTER("st_select_lex_unit::join_union_type_handlers");
+ SELECT_LEX *first_sl= first_select(), *sl= first_sl;
+ for (uint i= 0; i < count ; sl= sl->next_select(), i++)
+ {
+ Item *item;
+ List_iterator_fast<Item> it(sl->item_list);
+ for (uint pos= 0; (item= it++); pos++)
+ {
+ const Type_handler *item_type_handler= item->real_type_handler();
+ if (sl == first_sl)
+ holders[pos].set_handler(item_type_handler);
+ else
+ {
+ if (first_sl->item_list.elements != sl->item_list.elements)
+ {
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER_THD(thd_arg, ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),
+ MYF(0));
+ DBUG_RETURN(true);
+ }
+ if (holders[pos].aggregate_for_result(item_type_handler))
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ holders[pos].type_handler()->name().ptr(),
+ item_type_handler->name().ptr(),
+ "UNION");
+ DBUG_RETURN(true);
+ }
+ }
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ Aggregate data type attributes for the "count" leftmost UNION parts.
+*/
+bool st_select_lex_unit::join_union_type_attributes(THD *thd_arg,
+ Type_holder *holders,
+ uint count)
+{
+ DBUG_ENTER("st_select_lex_unit::join_union_type_attributes");
+ SELECT_LEX *sl, *first_sl= first_select();
+ uint item_pos;
+ for (uint pos= 0; pos < first_sl->item_list.elements; pos++)
+ {
+ if (holders[pos].alloc_arguments(thd_arg, count))
+ DBUG_RETURN(true);
+ }
+ for (item_pos= 0, sl= first_sl ;
+ item_pos < count;
+ sl= sl->next_select(), item_pos++)
+ {
+ Item *item_tmp;
+ List_iterator_fast<Item> itx(sl->item_list);
+ for (uint holder_pos= 0 ; (item_tmp= itx++); holder_pos++)
+ {
+ DBUG_ASSERT(item_tmp->fixed);
+ holders[holder_pos].add_argument(item_tmp);
+ }
+ }
+ for (uint pos= 0; pos < first_sl->item_list.elements; pos++)
+ {
+ if (holders[pos].aggregate_attributes(thd_arg))
+ DBUG_RETURN(true);
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ Join data types for the leftmost "count" UNION parts
+ and store corresponding Item_type_holder's into "types".
+*/
+bool st_select_lex_unit::join_union_item_types(THD *thd_arg,
+ List<Item> &types,
+ uint count)
+{
+ DBUG_ENTER("st_select_lex_unit::join_union_select_list_types");
+ SELECT_LEX *first_sl= first_select();
+ Type_holder *holders;
+
+ if (!(holders= new (thd_arg->mem_root)
+ Type_holder[first_sl->item_list.elements]) ||
+ join_union_type_handlers(thd_arg, holders, count) ||
+ join_union_type_attributes(thd_arg, holders, count))
+ DBUG_RETURN(true);
+
+ types.empty();
+ List_iterator_fast<Item> it(first_sl->item_list);
+ Item *item_tmp;
+ for (uint pos= 0; (item_tmp= it++); pos++)
+ {
+ /* Error's in 'new' will be detected after loop */
+ types.push_back(new (thd_arg->mem_root)
+ Item_type_holder(thd_arg,
+ &item_tmp->name,
+ holders[pos].type_handler(),
+ &holders[pos]/*Type_all_attributes*/,
+ holders[pos].get_maybe_null()));
+ }
+ if (thd_arg->is_fatal_error)
+ DBUG_RETURN(true); // out of memory
+ DBUG_RETURN(false);
+}
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
@@ -449,8 +872,10 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
SELECT_LEX *sl, *first_sl= first_select();
bool is_recursive= with_element && with_element->is_recursive;
bool is_rec_result_table_created= false;
+ uint union_part_count= 0;
select_result *tmp_result;
bool is_union_select;
+ bool have_except= FALSE, have_intersect= FALSE;
bool instantiate_tmp_table= false;
DBUG_ENTER("st_select_lex_unit::prepare");
DBUG_ASSERT(thd == thd_arg);
@@ -497,13 +922,28 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= sl= first_sl;
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
- is_union_select= is_union() || fake_select_lex;
+ is_union_select= is_unit_op() || fake_select_lex;
+ for (SELECT_LEX *s= first_sl; s; s= s->next_select())
+ {
+ switch (s->linkage)
+ {
+ case INTERSECT_TYPE:
+ have_intersect= TRUE;
+ break;
+ case EXCEPT_TYPE:
+ have_except= TRUE;
+ break;
+ default:
+ break;
+ }
+ }
/* Global option */
if (is_union_select || is_recursive)
{
- if (is_union() && !union_needs_tmp_table())
+ if (is_unit_op() && !union_needs_tmp_table() &&
+ !have_except && !have_intersect)
{
SELECT_LEX *last= first_select();
while (last->next_select())
@@ -518,7 +958,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
else
{
if (!is_recursive)
- union_result= new (thd_arg->mem_root) select_union(thd_arg);
+ union_result= new (thd_arg->mem_root) select_unit(thd_arg);
else
{
with_element->rec_result=
@@ -535,14 +975,22 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
tmp_result= sel_result;
sl->context.resolve_in_select_list= TRUE;
+
+ if (!is_union_select && !is_recursive)
+ {
+ if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
+ is_union_select))
+ goto err;
+ types= first_sl->item_list;
+ goto cont;
+ }
- for (;sl; sl= sl->next_select())
- {
- bool can_skip_order_by;
- sl->options|= SELECT_NO_UNLOCK;
- JOIN *join= new JOIN(thd_arg, sl->item_list,
- sl->options | thd_arg->variables.option_bits | additional_options,
- tmp_result);
+ for (;sl; sl= sl->next_select(), union_part_count++)
+ {
+ if (prepare_join(thd_arg, sl, tmp_result, additional_options,
+ is_union_select))
+ goto err;
+
/*
setup_tables_done_option should be set only for very first SELECT,
because it protect from secont setup_tables call for select-like non
@@ -550,93 +998,20 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
SELECT (for union it can be only INSERT ... SELECT).
*/
additional_options&= ~OPTION_SETUP_TABLES_DONE;
- if (!join)
- goto err;
-
- thd_arg->lex->current_select= sl;
-
- can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
-
- saved_error= join->prepare(sl->table_list.first,
- sl->with_wild,
- sl->where,
- (can_skip_order_by ? 0 :
- sl->order_list.elements) +
- sl->group_list.elements,
- can_skip_order_by ?
- NULL : sl->order_list.first,
- can_skip_order_by,
- sl->group_list.first,
- sl->having,
- (is_union_select ? NULL :
- thd_arg->lex->proc_list.first),
- sl, this);
-
- /* There are no * in the statement anymore (for PS) */
- sl->with_wild= 0;
- last_procedure= join->procedure;
-
- if (saved_error || (saved_error= thd_arg->is_fatal_error))
- goto err;
- /*
- Remove all references from the select_lex_units to the subqueries that
- are inside the ORDER BY clause.
- */
- if (can_skip_order_by)
- {
- for (ORDER *ord= (ORDER *)sl->order_list.first; ord; ord= ord->next)
- {
- (*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
- }
- }
/*
Use items list of underlaid select for derived tables to preserve
information about fields lengths and exact types
*/
- if (!is_union_select && !is_recursive)
- types= first_sl->item_list;
- else if (sl == first_sl)
+ if (sl == first_sl)
{
if (is_recursive)
{
if (derived->with->rename_columns_of_derived_unit(thd, this))
- goto err;
+ goto err;
if (check_duplicate_names(thd, sl->item_list, 0))
goto err;
}
- types.empty();
- List_iterator_fast<Item> it(sl->item_list);
- Item *item_tmp;
- while ((item_tmp= it++))
- {
- /* Error's in 'new' will be detected after loop */
- types.push_back(new (thd_arg->mem_root)
- Item_type_holder(thd_arg, item_tmp));
- }
-
- if (thd_arg->is_fatal_error)
- goto err; // out of memory
- }
- else
- {
- if (types.elements != sl->item_list.elements)
- {
- my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
- ER_THD(thd, ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
- goto err;
- }
- if (!is_rec_result_table_created)
- {
- List_iterator_fast<Item> it(sl->item_list);
- List_iterator_fast<Item> tp(types);
- Item *type, *item_tmp;
- while ((type= tp++, item_tmp= it++))
- {
- if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
- DBUG_RETURN(TRUE);
- }
- }
}
if (is_recursive)
{
@@ -649,11 +1024,15 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
ulonglong create_options;
create_options= (first_sl->options | thd_arg->variables.option_bits |
TMP_TABLE_ALL_COLUMNS);
+ // Join data types for all non-recursive parts of a recursive UNION
+ if (join_union_item_types(thd, types, union_part_count + 1))
+ goto err;
if (union_result->create_result_table(thd, &types,
MY_TEST(union_distinct),
create_options, derived->alias,
false,
- instantiate_tmp_table, false))
+ instantiate_tmp_table, false,
+ 0))
goto err;
if (!derived->table)
derived->table= derived->derived_result->table=
@@ -663,7 +1042,11 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
}
}
}
+ // In case of a non-recursive UNION, join data types for all UNION parts.
+ if (!is_recursive && join_union_item_types(thd, types, union_part_count))
+ goto err;
+cont:
/*
If the query is using select_union_direct, we have postponed
preparation of the underlying select_result until column types
@@ -734,12 +1117,48 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (global_parameters()->ftfunc_list->elements)
create_options= create_options | TMP_TABLE_FORCE_MYISAM;
-
- if (!is_recursive &&
- union_result->create_result_table(thd, &types, MY_TEST(union_distinct),
- create_options, "", false,
- instantiate_tmp_table, false))
- goto err;
+ if (!is_recursive)
+ {
+ uint hidden= 0;
+ if (have_intersect)
+ {
+ hidden= 1;
+ if (!intersect_mark)
+ {
+ /*
+ For intersect we add a hidden column first that contains
+ the current select number of the time when the row was
+ added to the temporary table
+ */
+
+ Query_arena *arena, backup_arena;
+ arena= thd->activate_stmt_arena_if_needed(&backup_arena);
+
+ intersect_mark= new (thd_arg->mem_root) Item_int(thd, 0);
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup_arena);
+
+ if (!intersect_mark)
+ goto err;
+ }
+ else
+ intersect_mark->value= 0; //reset
+ types.push_front(union_result->intersect_mark= intersect_mark);
+ union_result->intersect_mark->name.str= "___";
+ union_result->intersect_mark->name.length= 3;
+ }
+ bool error=
+ union_result->create_result_table(thd, &types,
+ MY_TEST(union_distinct),
+ create_options, "", false,
+ instantiate_tmp_table, false,
+ hidden);
+ if (intersect_mark)
+ types.pop();
+ if (error)
+ goto err;
+ }
if (fake_select_lex && !fake_select_lex->first_cond_optimization)
{
save_tablenr= result_table_list.tablenr_exec;
@@ -765,6 +1184,9 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
arena= thd->activate_stmt_arena_if_needed(&backup_arena);
saved_error= table->fill_item_list(&item_list);
+ // Item_list is inherited from 'types', so there could be the counter
+ if (intersect_mark)
+ item_list.pop(); // remove intersect counter
if (arena)
thd->restore_active_arena(arena, &backup_arena);
@@ -818,7 +1240,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
We're in execution of a prepared statement or stored procedure:
reset field items to point at fields from the created temporary table.
*/
- table->reset_item_list(&item_list);
+ table->reset_item_list(&item_list, intersect_mark ? 1 : 0);
}
}
@@ -955,6 +1377,8 @@ bool st_select_lex_unit::exec()
{
ha_rows records_at_start= 0;
thd->lex->current_select= sl;
+ if (union_result)
+ union_result->change_select();
if (fake_select_lex)
{
if (sl != &thd->lex->select_lex)
@@ -1349,7 +1773,7 @@ void st_select_lex_unit::reinit_exec_mechanism()
prepared= optimized= executed= 0;
optimize_started= 0;
#ifndef DBUG_OFF
- if (is_union())
+ if (is_unit_op())
{
List_iterator_fast<Item> it(item_list);
Item *field;
@@ -1431,7 +1855,7 @@ List<Item> *st_select_lex_unit::get_column_types(bool for_cursor)
}
- if (is_union())
+ if (is_unit_op())
{
DBUG_ASSERT(prepared);
/* Types are generated during prepare */
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 35e1fe24b97..568dd40df46 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -140,7 +140,7 @@ static bool check_fields(THD *thd, List<Item> &items)
if (!(field= item->field_for_view_update()))
{
/* item has name, because it comes from VIEW SELECT list */
- my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name.str);
return TRUE;
}
/*
@@ -1992,6 +1992,9 @@ loop_end:
TABLE *tbl= table;
do
{
+ LEX_CSTRING field_name;
+ field_name.str= tbl->alias.c_ptr();
+ field_name.length= strlen(field_name.str);
/*
Signal each table (including tables referenced by WITH CHECK OPTION
clause) for which we will store row position in the temporary table
@@ -2000,7 +2003,7 @@ loop_end:
tbl->prepare_for_position();
Field_string *field= new Field_string(tbl->file->ref_length, 0,
- tbl->alias.c_ptr(),
+ &field_name,
&my_charset_bin);
if (!field)
DBUG_RETURN(1);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 55550ddfb8a..5e0cd57f2d9 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -39,7 +39,7 @@
#define MD5_BUFF_LENGTH 33
-const LEX_STRING view_type= { C_STRING_WITH_LEN("VIEW") };
+const LEX_CSTRING view_type= { STRING_WITH_LEN("VIEW") };
static int mysql_register_view(THD *, TABLE_LIST *, enum_view_create_mode);
@@ -63,9 +63,9 @@ static void make_unique_view_field_name(THD *thd, Item *target,
List<Item> &item_list,
Item *last_element)
{
- char *name= (target->orig_name ?
- target->orig_name :
- target->name);
+ const char *name= (target->orig_name ?
+ target->orig_name :
+ target->name.str);
size_t name_len;
uint attempt;
char buff[NAME_LEN+1];
@@ -85,7 +85,7 @@ static void make_unique_view_field_name(THD *thd, Item *target,
{
check= itc++;
if (check != target &&
- my_strcasecmp(system_charset_info, buff, check->name) == 0)
+ my_strcasecmp(system_charset_info, buff, check->name.str) == 0)
{
ok= FALSE;
break;
@@ -96,7 +96,7 @@ static void make_unique_view_field_name(THD *thd, Item *target,
itc.rewind();
}
- target->orig_name= target->name;
+ target->orig_name= target->name.str;
target->set_name(thd, buff, name_len, system_charset_info);
}
@@ -140,7 +140,7 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view
itc.rewind();
while ((check= itc++) && check != item)
{
- if (my_strcasecmp(system_charset_info, item->name, check->name) == 0)
+ if (my_strcasecmp(system_charset_info, item->name.str, check->name.str) == 0)
{
if (!gen_unique_view_name)
goto err;
@@ -156,7 +156,7 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view
DBUG_RETURN(FALSE);
err:
- my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
+ my_error(ER_DUP_FIELDNAME, MYF(0), item->name.str);
DBUG_RETURN(TRUE);
}
@@ -178,10 +178,10 @@ void make_valid_column_names(THD *thd, List<Item> &item_list)
for (uint column_no= 1; (item= it++); column_no++)
{
- if (!item->is_autogenerated_name || !check_column_name(item->name))
+ if (!item->is_autogenerated_name || !check_column_name(item->name.str))
continue;
name_len= my_snprintf(buff, NAME_LEN, "Name_exp_%u", column_no);
- item->orig_name= item->name;
+ item->orig_name= item->name.str;
item->set_name(thd, buff, name_len, system_charset_info);
}
@@ -225,10 +225,10 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
view->definer.user= decoy.definer.user;
lex->definer= &view->definer;
}
- if (lex->create_view_algorithm == VIEW_ALGORITHM_INHERIT)
- lex->create_view_algorithm= (uint8) decoy.algorithm;
- if (lex->create_view_suid == VIEW_SUID_DEFAULT)
- lex->create_view_suid= decoy.view_suid ?
+ if (lex->create_view->algorithm == VIEW_ALGORITHM_INHERIT)
+ lex->create_view->algorithm= (uint8) decoy.algorithm;
+ if (lex->create_view->suid == VIEW_SUID_DEFAULT)
+ lex->create_view->suid= decoy.view_suid ?
VIEW_SUID_DEFINER : VIEW_SUID_INVOKER;
return FALSE;
@@ -602,7 +602,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
{
Item_field *fld= item->field_for_view_update();
uint priv= (get_column_grant(thd, &view->grant, view->db,
- view->table_name, item->name) &
+ view->table_name, item->name.str) &
VIEW_ANY_ACL);
if (fld && !fld->field->table->s->tmp_table)
@@ -620,7 +620,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
{
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
"create view", thd->security_ctx->priv_user,
- thd->security_ctx->priv_host, report_item->name,
+ thd->security_ctx->priv_host, report_item->name.str,
view->table_name);
res= TRUE;
goto err;
@@ -647,8 +647,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
{ C_STRING_WITH_LEN("ALTER ") },
{ C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
- buff.append(command[thd->lex->create_view_mode].str,
- command[thd->lex->create_view_mode].length);
+ buff.append(command[thd->lex->create_view->mode].str,
+ command[thd->lex->create_view->mode].length);
view_store_options(thd, views, &buff);
buff.append(STRING_WITH_LEN("VIEW "));
@@ -683,8 +683,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
buff.append(views->source.str, views->source.length);
int errcode= query_error_code(thd, TRUE);
+ /*
+ Don't log any unsafe warnings for CREATE VIEW as it's safely replicated
+ with statement based replication
+ */
+ thd->reset_unsafe_warnings();
if (thd->binlog_query(THD::STMT_QUERY_TYPE,
- buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode))
+ buff.ptr(), buff.length(), FALSE, FALSE, FALSE,
+ errcode))
res= TRUE;
}
@@ -705,11 +711,11 @@ err:
}
-static void make_view_filename(LEX_STRING *dir, char *dir_buff,
+static void make_view_filename(LEX_CSTRING *dir, char *dir_buff,
size_t dir_buff_len,
- LEX_STRING *path, char *path_buff,
+ LEX_CSTRING *path, char *path_buff,
size_t path_buff_len,
- LEX_STRING *file,
+ LEX_CSTRING *file,
TABLE_LIST *view)
{
/* print file name */
@@ -735,37 +741,37 @@ static const int required_view_parameters= 15;
parse()
*/
static File_option view_parameters[]=
-{{{ C_STRING_WITH_LEN("query")},
+{{{ STRING_WITH_LEN("query")},
my_offsetof(TABLE_LIST, select_stmt),
FILE_OPTIONS_ESTRING},
- {{ C_STRING_WITH_LEN("md5")},
+ {{ STRING_WITH_LEN("md5")},
my_offsetof(TABLE_LIST, md5),
FILE_OPTIONS_STRING},
- {{ C_STRING_WITH_LEN("updatable")},
+ {{ STRING_WITH_LEN("updatable")},
my_offsetof(TABLE_LIST, updatable_view),
FILE_OPTIONS_ULONGLONG},
- {{ C_STRING_WITH_LEN("algorithm")},
+ {{ STRING_WITH_LEN("algorithm")},
my_offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_VIEW_ALGO},
- {{ C_STRING_WITH_LEN("definer_user")},
+ {{ STRING_WITH_LEN("definer_user")},
my_offsetof(TABLE_LIST, definer.user),
FILE_OPTIONS_STRING},
- {{ C_STRING_WITH_LEN("definer_host")},
+ {{ STRING_WITH_LEN("definer_host")},
my_offsetof(TABLE_LIST, definer.host),
FILE_OPTIONS_STRING},
- {{ C_STRING_WITH_LEN("suid")},
+ {{ STRING_WITH_LEN("suid")},
my_offsetof(TABLE_LIST, view_suid),
FILE_OPTIONS_ULONGLONG},
- {{ C_STRING_WITH_LEN("with_check_option")},
+ {{ STRING_WITH_LEN("with_check_option")},
my_offsetof(TABLE_LIST, with_check),
FILE_OPTIONS_ULONGLONG},
- {{ C_STRING_WITH_LEN("timestamp")},
+ {{ STRING_WITH_LEN("timestamp")},
my_offsetof(TABLE_LIST, timestamp),
FILE_OPTIONS_TIMESTAMP},
- {{ C_STRING_WITH_LEN("create-version")},
+ {{ STRING_WITH_LEN("create-version")},
my_offsetof(TABLE_LIST, file_version),
FILE_OPTIONS_ULONGLONG},
- {{ C_STRING_WITH_LEN("source")},
+ {{ STRING_WITH_LEN("source")},
my_offsetof(TABLE_LIST, source),
FILE_OPTIONS_ESTRING},
{{(char*) STRING_WITH_LEN("client_cs_name")},
@@ -777,21 +783,21 @@ static File_option view_parameters[]=
{{(char*) STRING_WITH_LEN("view_body_utf8")},
my_offsetof(TABLE_LIST, view_body_utf8),
FILE_OPTIONS_ESTRING},
- {{ C_STRING_WITH_LEN("mariadb-version")},
+ {{ STRING_WITH_LEN("mariadb-version")},
my_offsetof(TABLE_LIST, mariadb_version),
FILE_OPTIONS_ULONGLONG},
{{NullS, 0}, 0,
FILE_OPTIONS_STRING}
};
-static LEX_STRING view_file_type[]= {{(char*) STRING_WITH_LEN("VIEW") }};
+static LEX_CSTRING view_file_type[]= {{STRING_WITH_LEN("VIEW") }};
int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum,
bool swap_alg)
{
char dir_buff[FN_REFLEN + 1], path_buff[FN_REFLEN + 1];
- LEX_STRING dir, file, path;
+ LEX_CSTRING dir, file, path;
DBUG_ENTER("mariadb_fix_view");
if (!wrong_checksum && view->mariadb_version)
@@ -906,7 +912,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
char md5[MD5_BUFF_LENGTH];
bool can_be_merged;
char dir_buff[FN_REFLEN + 1], path_buff[FN_REFLEN + 1];
- LEX_STRING dir, file, path;
+ LEX_CSTRING dir, file, path;
int error= 0;
DBUG_ENTER("mysql_register_view");
@@ -928,7 +934,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
DBUG_PRINT("info", ("View: %.*s", view_query.length(), view_query.ptr()));
/* fill structure */
- view->source= thd->lex->create_view_select;
+ view->source= thd->lex->create_view->select;
if (!thd->make_lex_string(&view->select_stmt, view_query.ptr(),
view_query.length()))
@@ -953,18 +959,18 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
}
view->md5.length= 32;
can_be_merged= lex->can_be_merged();
- if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
+ if (lex->create_view->algorithm == VIEW_ALGORITHM_MERGE &&
!lex->can_be_merged())
{
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
ER_THD(thd, ER_WARN_VIEW_MERGE));
- lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
+ lex->create_view->algorithm= DTYPE_ALGORITHM_UNDEFINED;
}
- view->algorithm= lex->create_view_algorithm;
+ view->algorithm= lex->create_view->algorithm;
view->definer.user= lex->definer->user;
view->definer.host= lex->definer->host;
- view->view_suid= lex->create_view_suid;
- view->with_check= lex->create_view_check;
+ view->view_suid= lex->create_view->suid;
+ view->with_check= lex->create_view->check;
DBUG_EXECUTE_IF("simulate_register_view_failure",
{
@@ -1008,14 +1014,14 @@ loop_out:
/* check old .frm */
{
char path_buff[FN_REFLEN];
- LEX_STRING path;
+ LEX_CSTRING path;
File_parser *parser;
path.str= path_buff;
fn_format(path_buff, file.str, dir.str, "", MY_UNPACK_FILENAME);
path.length= strlen(path_buff);
- if (ha_table_exists(thd, view->db, view->table_name, NULL))
+ if (ha_table_exists(thd, view->db, view->table_name))
{
if (lex->create_info.if_not_exists())
{
@@ -1095,7 +1101,7 @@ loop_out:
UNION
*/
if (view->updatable_view &&
- !lex->select_lex.master_unit()->is_union() &&
+ !lex->select_lex.master_unit()->is_unit_op() &&
!(lex->select_lex.table_list.first)->next_local &&
find_table_in_global_list(lex->query_tables->next_global,
lex->query_tables->db,
@@ -1153,7 +1159,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
DBUG_ENTER("mysql_make_view");
DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name));
- if (table->required_type == FRMTYPE_TABLE)
+ if (table->required_type == TABLE_TYPE_NORMAL)
{
my_error(ER_WRONG_OBJECT, MYF(0), share->db.str, share->table_name.str,
"BASE TABLE");
@@ -1327,7 +1333,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
{
char old_db_buf[SAFE_NAME_LEN+1];
- LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
+ LEX_CSTRING old_db= { old_db_buf, sizeof(old_db_buf) };
bool dbchanged;
Parser_state parser_state;
if (parser_state.init(thd, table->select_stmt.str,
@@ -1338,7 +1344,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
Use view db name as thread default database, in order to ensure
that the view is parsed and prepared correctly.
*/
- if ((result= mysql_opt_change_db(thd, &table->view_db, &old_db, 1,
+ if ((result= mysql_opt_change_db(thd, &table->view_db,
+ (LEX_STRING*) &old_db, 1,
&dbchanged)))
goto end;
@@ -1357,7 +1364,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
* MODE_NO_UNSIGNED_SUBTRACTION affect execution
- MODE_NO_DIR_IN_CREATE affect table creation only
- MODE_POSTGRESQL compounded from other modes
- - MODE_ORACLE compounded from other modes
+ - MODE_ORACLE affects Item creation (e.g for CONCAT)
- MODE_MSSQL compounded from other modes
- MODE_DB2 compounded from other modes
- MODE_MAXDB affect only CREATE TABLE parsing
@@ -1372,7 +1379,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
+ MODE_NO_BACKSLASH_ESCAPES affect expression parsing
*/
thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
- MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
+ MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES |
+ MODE_ORACLE);
/* Parse the query. */
@@ -1541,7 +1549,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
*/
for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
{
- tbl->lock_type= table->lock_type;
+ /* We have to keep the lock type for sequence tables */
+ if (!tbl->sequence)
+ tbl->lock_type= table->lock_type;
tbl->mdl_request.set_type((tbl->lock_type >= TL_WRITE_ALLOW_WRITE) ?
MDL_SHARED_WRITE : MDL_SHARED_READ);
}
@@ -1672,7 +1682,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
We can safely ignore the VIEW's ORDER BY if we merge into union
branch, as order is not important there.
*/
- if (!table->select_lex->master_unit()->is_union() &&
+ if (!table->select_lex->master_unit()->is_unit_op() &&
table->select_lex->order_list.elements == 0)
table->select_lex->order_list.push_back(&lex->select_lex.order_list);
else
@@ -1680,7 +1690,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
if (old_lex->sql_command == SQLCOM_SELECT &&
(old_lex->describe & DESCRIBE_EXTENDED) &&
lex->select_lex.order_list.elements &&
- !table->select_lex->master_unit()->is_union())
+ !table->select_lex->master_unit()->is_unit_op())
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_VIEW_ORDERBY_IGNORED,
@@ -1763,7 +1773,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
char path[FN_REFLEN + 1];
TABLE_LIST *view;
String non_existant_views;
- char *wrong_object_db= NULL, *wrong_object_name= NULL;
+ const char *wrong_object_db= NULL, *wrong_object_name= NULL;
bool error= FALSE;
bool some_views_deleted= FALSE;
bool something_wrong= FALSE;
@@ -1797,8 +1807,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
if (thd->lex->if_exists())
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_BAD_TABLE_ERROR,
- ER_THD(thd, ER_BAD_TABLE_ERROR),
+ ER_UNKNOWN_VIEW,
+ ER_THD(thd, ER_UNKNOWN_VIEW),
name);
continue;
}
@@ -1840,7 +1850,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
}
if (non_existant_views.length())
{
- my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr_safe());
+ my_error(ER_UNKNOWN_VIEW, MYF(0), non_existant_views.c_ptr_safe());
}
something_wrong= error || wrong_object_name || non_existant_views.length();
@@ -2128,7 +2138,7 @@ mysql_rename_view(THD *thd,
const char *new_name,
TABLE_LIST *view)
{
- LEX_STRING pathstr;
+ LEX_CSTRING pathstr;
File_parser *parser;
char path_buff[FN_REFLEN + 1];
bool error= TRUE;
@@ -2144,7 +2154,7 @@ mysql_rename_view(THD *thd,
{
TABLE_LIST view_def;
char dir_buff[FN_REFLEN + 1];
- LEX_STRING dir, file;
+ LEX_CSTRING dir, file;
/*
To be PS-friendly we should either to restore state of
diff --git a/sql/sql_view.h b/sql/sql_view.h
index b9eb92198f8..ff94d2de935 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -60,7 +60,7 @@ void make_valid_column_names(THD *thd, List<Item> &item_list);
#define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL)
-extern const LEX_STRING view_type;
+extern const LEX_CSTRING view_type;
void make_valid_column_names(List<Item> &item_list);
diff --git a/sql/sql_window.cc b/sql/sql_window.cc
index 0e407308d4e..74e1ad25183 100644
--- a/sql/sql_window.cc
+++ b/sql/sql_window.cc
@@ -12,13 +12,13 @@ Window_spec::check_window_names(List_iterator_fast<Window_spec> &it)
{
if (window_names_are_checked)
return false;
- char *name= this->name();
- char *ref_name= window_reference();
+ const char *name= this->name();
+ const char *ref_name= window_reference();
it.rewind();
Window_spec *win_spec;
while((win_spec= it++) && win_spec != this)
{
- char *win_spec_name= win_spec->name();
+ const char *win_spec_name= win_spec->name();
if (!win_spec_name)
break;
if (name && my_strcasecmp(system_charset_info, name, win_spec_name) == 0)
@@ -384,8 +384,8 @@ int compare_window_frame_bounds(Window_frame_bound *win_frame_bound1,
return CMP_EQ;
else
{
- res= strcmp(win_frame_bound1->offset->name,
- win_frame_bound2->offset->name);
+ res= strcmp(win_frame_bound1->offset->name.str,
+ win_frame_bound2->offset->name.str);
res= res > 0 ? CMP_GT : CMP_LT;
if (is_bottom_bound)
res= -res;
diff --git a/sql/sql_window.h b/sql/sql_window.h
index 6a56fc84392..ed1d9e36492 100644
--- a/sql/sql_window.h
+++ b/sql/sql_window.h
@@ -96,7 +96,7 @@ class Window_spec : public Sql_alloc
public:
virtual ~Window_spec() {}
- LEX_STRING *window_ref;
+ LEX_CSTRING *window_ref;
SQL_I_List<ORDER> *partition_list;
@@ -106,7 +106,7 @@ class Window_spec : public Sql_alloc
Window_spec *referenced_win_spec;
- Window_spec(LEX_STRING *win_ref,
+ Window_spec(LEX_CSTRING *win_ref,
SQL_I_List<ORDER> *part_list,
SQL_I_List<ORDER> *ord_list,
Window_frame *win_frame)
@@ -114,11 +114,14 @@ class Window_spec : public Sql_alloc
partition_list(part_list), order_list(ord_list),
window_frame(win_frame), referenced_win_spec(NULL) {}
- virtual char *name() { return NULL; }
+ virtual const char *name() { return NULL; }
bool check_window_names(List_iterator_fast<Window_spec> &it);
- char *window_reference() { return window_ref ? window_ref->str : NULL; }
+ const char *window_reference()
+ {
+ return window_ref ? window_ref->str : NULL;
+ }
void join_partition_and_order_lists()
{
@@ -138,17 +141,17 @@ class Window_def : public Window_spec
{
public:
- LEX_STRING *window_name;
+ LEX_CSTRING *window_name;
- Window_def(LEX_STRING *win_name,
- LEX_STRING *win_ref,
+ Window_def(LEX_CSTRING *win_name,
+ LEX_CSTRING *win_ref,
SQL_I_List<ORDER> *part_list,
SQL_I_List<ORDER> *ord_list,
Window_frame *win_frame)
: Window_spec(win_ref, part_list, ord_list, win_frame),
window_name(win_name) {}
- char *name() { return window_name->str; }
+ const char *name() { return window_name->str; }
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2d692e9e53b..c9c922f6a55 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -65,6 +65,8 @@
#include "set_var.h"
#include "rpl_mi.h"
#include "lex_token.h"
+#include "sql_lex.h"
+#include "sql_sequence.h"
/* this is to get the bison compilation windows warnings out */
#ifdef _MSC_VER
@@ -98,7 +100,7 @@ int yylex(void *yylval, void *yythd);
#define MYSQL_YYABORT_UNLESS(A) \
if (!(A)) \
{ \
- my_parse_error(thd, ER_SYNTAX_ERROR); \
+ thd->parse_error(); \
MYSQL_YYABORT; \
}
@@ -111,43 +113,6 @@ int yylex(void *yylval, void *yythd);
#define YYDEBUG 0
#endif
-/**
- @brief Push an error message into MySQL error stack with line
- and position information.
-
- This function provides semantic action implementers with a way
- to push the famous "You have a syntax error near..." error
- message into the error stack, which is normally produced only if
- a parse error is discovered internally by the Bison generated
- parser.
-*/
-
-static void my_parse_error_intern(THD *thd, const char *err_text,
- const char *yytext)
-{
- Lex_input_stream *lip= &thd->m_parser_state->m_lip;
- if (!yytext)
- {
- if (!(yytext= lip->get_tok_start()))
- yytext= "";
- }
- /* Push an error into the error stack */
- ErrConvString err(yytext, strlen(yytext),
- thd->variables.character_set_client);
- my_error(ER_PARSE_ERROR, MYF(0), err_text, err.ptr(), lip->yylineno);
-}
-
-
-static void my_parse_error(THD *thd, uint err_number, const char *yytext=0)
-{
- return my_parse_error_intern(thd, ER_THD(thd, err_number), yytext);
-}
-
-void LEX::parse_error()
-{
- my_parse_error(thd, ER_SYNTAX_ERROR);
-}
-
/**
@brief Bison callback to report a syntax/OOM error
@@ -164,7 +129,7 @@ void LEX::parse_error()
This function is not for use in semantic actions and is internal to
the parser, as it performs some pre-return cleanup.
- In semantic actions, please use my_parse_error or my_error to
+ In semantic actions, please use thd->parse_error() or my_error to
push an error into the error stack and MYSQL_YYABORT
to abort from the parser.
*/
@@ -181,7 +146,7 @@ void MYSQLerror(THD *thd, const char *s)
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
s= ER_THD(thd, ER_SYNTAX_ERROR);
- my_parse_error_intern(thd, s, 0);
+ thd->parse_error(s, 0);
}
@@ -207,80 +172,6 @@ void turn_parser_debug_on()
}
#endif
-static bool is_native_function(THD *thd, const LEX_STRING *name)
-{
- if (find_native_function_builder(thd, *name))
- return true;
-
- if (is_lex_native_function(name))
- return true;
-
- return false;
-}
-
-
-static sp_head *make_sp_head(THD *thd, sp_name *name,
- enum stored_procedure_type type)
-{
- LEX *lex= thd->lex;
- sp_head *sp;
-
- /* Order is important here: new - reset - init */
- if ((sp= new sp_head()))
- {
- sp->reset_thd_mem_root(thd);
- sp->init(lex);
- sp->m_type= type;
- if (name)
- sp->init_sp_name(thd, name);
- sp->m_chistics= &lex->sp_chistics;
- lex->sphead= sp;
- }
- bzero(&lex->sp_chistics, sizeof(lex->sp_chistics));
- return sp;
-}
-
-static bool maybe_start_compound_statement(THD *thd)
-{
- if (!thd->lex->sphead)
- {
- if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
- return 1;
-
- Lex->sp_chistics.suid= SP_IS_NOT_SUID;
- Lex->sphead->set_body_start(thd, YYLIP->get_cpp_ptr());
- }
- return 0;
-}
-
-static bool push_sp_label(THD *thd, LEX_STRING label)
-{
- sp_pcontext *ctx= thd->lex->spcont;
- sp_label *lab= ctx->find_label(label);
-
- if (lab)
- {
- my_error(ER_SP_LABEL_REDEFINE, MYF(0), label.str);
- return 1;
- }
- else
- {
- lab= thd->lex->spcont->push_label(thd, label,
- thd->lex->sphead->instructions());
- lab->type= sp_label::ITERATION;
- }
- return 0;
-}
-
-static bool push_sp_empty_label(THD *thd)
-{
- if (maybe_start_compound_statement(thd))
- return 1;
- /* Unlabeled controls get an empty label. */
- thd->lex->spcont->push_label(thd, empty_lex_str,
- thd->lex->sphead->instructions());
- return 0;
-}
/**
Helper action for a case expression statement (the expr in 'CASE expr').
@@ -290,22 +181,20 @@ static bool push_sp_empty_label(THD *thd)
@return 0 on success
*/
-int case_stmt_action_expr(LEX *lex, Item* expr)
+int LEX::case_stmt_action_expr(Item* expr)
{
- sp_head *sp= lex->sphead;
- sp_pcontext *parsing_ctx= lex->spcont;
- int case_expr_id= parsing_ctx->register_case_expr();
+ int case_expr_id= spcont->register_case_expr();
sp_instr_set_case_expr *i;
- if (parsing_ctx->push_case_expr_id(case_expr_id))
+ if (spcont->push_case_expr_id(case_expr_id))
return 1;
- i= new (lex->thd->mem_root)
- sp_instr_set_case_expr(sp->instructions(), parsing_ctx, case_expr_id, expr,
- lex);
+ i= new (thd->mem_root)
+ sp_instr_set_case_expr(sphead->instructions(), spcont, case_expr_id, expr,
+ this);
- sp->add_cont_backpatch(i);
- return sp->add_instr(i);
+ sphead->add_cont_backpatch(i);
+ return sphead->add_instr(i);
}
/**
@@ -316,33 +205,30 @@ int case_stmt_action_expr(LEX *lex, Item* expr)
@param simple true for simple cases, false for searched cases
*/
-int case_stmt_action_when(LEX *lex, Item *when, bool simple)
+int LEX::case_stmt_action_when(Item *when, bool simple)
{
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- uint ip= sp->instructions();
+ uint ip= sphead->instructions();
sp_instr_jump_if_not *i;
Item_case_expr *var;
Item *expr;
- THD *thd= lex->thd;
if (simple)
{
var= new (thd->mem_root)
- Item_case_expr(thd, ctx->get_current_case_expr_id());
+ Item_case_expr(thd, spcont->get_current_case_expr_id());
#ifndef DBUG_OFF
if (var)
{
- var->m_sp= sp;
+ var->m_sp= sphead;
}
#endif
expr= new (thd->mem_root) Item_func_eq(thd, var, when);
- i= new (thd->mem_root) sp_instr_jump_if_not(ip, ctx, expr, lex);
+ i= new (thd->mem_root) sp_instr_jump_if_not(ip, spcont, expr, this);
}
else
- i= new (thd->mem_root) sp_instr_jump_if_not(ip, ctx, when, lex);
+ i= new (thd->mem_root) sp_instr_jump_if_not(ip, spcont, when, this);
/*
BACKPATCH: Registering forward jump from
@@ -350,10 +236,11 @@ int case_stmt_action_when(LEX *lex, Item *when, bool simple)
(jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
*/
- return !MY_TEST(i) ||
- sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0)) ||
- sp->add_cont_backpatch(i) ||
- sp->add_instr(i);
+ return
+ !MY_TEST(i) ||
+ sphead->push_backpatch(thd, i, spcont->push_label(thd, &empty_clex_str, 0)) ||
+ sphead->add_cont_backpatch(i) ||
+ sphead->add_instr(i);
}
/**
@@ -362,13 +249,11 @@ int case_stmt_action_when(LEX *lex, Item *when, bool simple)
@param lex the parser lex context
*/
-int case_stmt_action_then(LEX *lex)
+int LEX::case_stmt_action_then()
{
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- uint ip= sp->instructions();
- sp_instr_jump *i= new (lex->thd->mem_root) sp_instr_jump(ip, ctx);
- if (!MY_TEST(i) || sp->add_instr(i))
+ uint ip= sphead->instructions();
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(ip, spcont);
+ if (!MY_TEST(i) || sphead->add_instr(i))
return 1;
/*
@@ -377,7 +262,7 @@ int case_stmt_action_then(LEX *lex)
(jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
*/
- sp->backpatch(ctx->pop_label());
+ sphead->backpatch(spcont->pop_label());
/*
BACKPATCH: Registering forward jump from
@@ -385,18 +270,7 @@ int case_stmt_action_then(LEX *lex)
(jump from instruction 4 to 12, 7 to 12 ... in the example)
*/
- return sp->push_backpatch(lex->thd, i, ctx->last_label());
-}
-
-static bool
-find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
-{
- tmp->var= find_sys_var(thd, tmp->base_name.str, tmp->base_name.length);
-
- if (tmp->var != NULL)
- tmp->base_name= null_lex_str;
-
- return thd->is_error();
+ return sphead->push_backpatch(thd, i, spcont->last_label());
}
@@ -404,7 +278,6 @@ find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
Helper action for a SET statement.
Used to push a system variable into the assignment list.
- @param thd the current thread
@param tmp the system variable with base name
@param var_type the scope of the variable
@param val the value being assigned to the variable
@@ -412,16 +285,15 @@ find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
@return TRUE if error, FALSE otherwise.
*/
-static bool
-set_system_variable(THD *thd, struct sys_var_with_base *tmp,
- enum enum_var_type var_type, Item *val)
+bool
+LEX::set_system_variable(struct sys_var_with_base *tmp,
+ enum enum_var_type var_type, Item *val)
{
set_var *var;
- LEX *lex= thd->lex;
/* No AUTOCOMMIT from a stored function or trigger. */
- if (lex->spcont && tmp->var == Sys_autocommit_ptr)
- lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ if (spcont && tmp->var == Sys_autocommit_ptr)
+ sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
if (val && val->type() == Item::FIELD_ITEM &&
((Item_field*)val)->table_name)
@@ -434,45 +306,7 @@ set_system_variable(THD *thd, struct sys_var_with_base *tmp,
set_var(thd, var_type, tmp->var, &tmp->base_name, val)))
return TRUE;
- return lex->var_list.push_back(var, thd->mem_root);
-}
-
-
-/**
- Helper action for a SET statement.
- Used to push a SP local variable into the assignment list.
-
- @param thd the current thread
- @param var_type the SP local variable
- @param val the value being assigned to the variable
-
- @return TRUE if error, FALSE otherwise.
-*/
-
-static bool
-set_local_variable(THD *thd, sp_variable *spv, Item *val)
-{
- Item *it;
- LEX *lex= thd->lex;
- sp_instr_set *sp_set;
-
- if (val)
- it= val;
- else if (spv->default_value)
- it= spv->default_value;
- else
- {
- it= new (thd->mem_root) Item_null(thd);
- if (it == NULL)
- return TRUE;
- }
-
- sp_set= new (thd->mem_root)
- sp_instr_set(lex->sphead->instructions(), lex->spcont,
- spv->offset, it, spv->sql_type(),
- lex, TRUE);
-
- return (sp_set == NULL || lex->sphead->add_instr(sp_set));
+ return var_list.push_back(var, thd->mem_root);
}
@@ -480,17 +314,14 @@ set_local_variable(THD *thd, sp_variable *spv, Item *val)
Helper action for a SET statement.
Used to SET a field of NEW row.
- @param thd the current thread
@param name the field name
@param val the value being assigned to the row
@return TRUE if error, FALSE otherwise.
*/
-static bool
-set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
+bool LEX::set_trigger_new_row(LEX_CSTRING *name, Item *val)
{
- LEX *lex= thd->lex;
Item_trigger_field *trg_fld;
sp_instr_set_trigger_field *sp_fld;
@@ -498,22 +329,21 @@ set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
if (! val)
val= new (thd->mem_root) Item_null(thd);
- DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
- (lex->trg_chistics.event == TRG_EVENT_INSERT ||
- lex->trg_chistics.event == TRG_EVENT_UPDATE));
+ DBUG_ASSERT(trg_chistics.action_time == TRG_ACTION_BEFORE &&
+ (trg_chistics.event == TRG_EVENT_INSERT ||
+ trg_chistics.event == TRG_EVENT_UPDATE));
trg_fld= new (thd->mem_root)
- Item_trigger_field(thd, lex->current_context(),
+ Item_trigger_field(thd, current_context(),
Item_trigger_field::NEW_ROW,
- name->str, UPDATE_ACL, FALSE);
+ name, UPDATE_ACL, FALSE);
if (trg_fld == NULL)
return TRUE;
sp_fld= new (thd->mem_root)
- sp_instr_set_trigger_field(lex->sphead->instructions(),
- lex->spcont, trg_fld, val,
- lex);
+ sp_instr_set_trigger_field(sphead->instructions(),
+ spcont, trg_fld, val, this);
if (sp_fld == NULL)
return TRUE;
@@ -522,16 +352,15 @@ set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
Let us add this item to list of all Item_trigger_field
objects in trigger.
*/
- lex->trg_table_fields.link_in_list(trg_fld, &trg_fld->next_trg_field);
+ trg_table_fields.link_in_list(trg_fld, &trg_fld->next_trg_field);
- return lex->sphead->add_instr(sp_fld);
+ return sphead->add_instr(sp_fld);
}
/**
Create an object to represent a SP variable in the Item-hierarchy.
- @param thd The current thread.
@param name The SP variable name.
@param spvar The SP variable (optional).
@param start_in_q Start position of the SP variable name in the query.
@@ -543,29 +372,27 @@ set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val)
@return An Item_splocal object representing the SP variable, or NULL on error.
*/
-static Item_splocal*
-create_item_for_sp_var(THD *thd, LEX_STRING name, sp_variable *spvar,
- const char *start_in_q, const char *end_in_q)
+Item_splocal*
+LEX::create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar,
+ const char *start_in_q, const char *end_in_q)
{
Item_splocal *item;
- LEX *lex= thd->lex;
uint pos_in_q, len_in_q;
- sp_pcontext *spc = lex->spcont;
/* If necessary, look for the variable. */
- if (spc && !spvar)
- spvar= spc->find_variable(name, false);
+ if (spcont && !spvar)
+ spvar= spcont->find_variable(name, false);
if (!spvar)
{
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), name.str);
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), name->str);
return NULL;
}
- DBUG_ASSERT(spc && spvar);
+ DBUG_ASSERT(spcont && spvar);
/* Position and length of the SP variable name in the query. */
- pos_in_q= start_in_q - lex->sphead->m_tmp_query;
+ pos_in_q= start_in_q - sphead->m_tmp_query;
len_in_q= end_in_q - start_in_q;
item= new (thd->mem_root)
@@ -574,7 +401,7 @@ create_item_for_sp_var(THD *thd, LEX_STRING name, sp_variable *spvar,
#ifndef DBUG_OFF
if (item)
- item->m_sp= lex->sphead;
+ item->m_sp= sphead;
#endif
return item;
@@ -673,58 +500,75 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
@return <code>false</code> if successful, <code>true</code> if an error was
reported. In the latter case parsing should stop.
*/
-bool add_select_to_union_list(LEX *lex, bool is_union_distinct,
- bool is_top_level)
+bool LEX::add_select_to_union_list(bool is_union_distinct,
+ enum sub_select_type type,
+ bool is_top_level)
{
- /*
+ const char *type_name= (type == INTERSECT_TYPE ? "INTERSECT" :
+ (type == EXCEPT_TYPE ? "EXCEPT" : "UNION"));
+ /*
Only the last SELECT can have INTO. Since the grammar won't allow INTO in
a nested SELECT, we make this check only when creating a top-level SELECT.
*/
- if (is_top_level && lex->result)
+ if (is_top_level && result)
{
- my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
+ my_error(ER_WRONG_USAGE, MYF(0), type_name, "INTO");
return TRUE;
}
- if (lex->current_select->order_list.first && !lex->current_select->braces)
+ if (current_select->order_list.first && !current_select->braces)
{
- my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
+ my_error(ER_WRONG_USAGE, MYF(0), type_name, "ORDER BY");
return TRUE;
}
- if (lex->current_select->explicit_limit && !lex->current_select->braces)
+ if (current_select->explicit_limit && !current_select->braces)
{
- my_error(ER_WRONG_USAGE, MYF(0), "UNION", "LIMIT");
+ my_error(ER_WRONG_USAGE, MYF(0), type_name, "LIMIT");
return TRUE;
}
- if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+ if (current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- my_parse_error(lex->thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
return TRUE;
}
+ if (!is_union_distinct && (type == INTERSECT_TYPE || type == EXCEPT_TYPE))
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), type_name, "ALL");
+ return TRUE;
+ }
+ /*
+ Priority implementation, but also trying to keep things as flat
+ as possible */
+ if (type == INTERSECT_TYPE &&
+ (current_select->linkage != INTERSECT_TYPE &&
+ current_select != current_select->master_unit()->first_select()))
+ {
+ /*
+ This and previous SELECTs should go one level down because of
+ priority
+ */
+ SELECT_LEX *prev= exclude_last_select();
+ if (add_unit_in_brackets(prev))
+ return TRUE;
+ return add_select_to_union_list(is_union_distinct, type, 0);
+ }
+ else
+ {
+ check_automatic_up(type);
+ }
/* This counter shouldn't be incremented for UNION parts */
- lex->nest_level--;
- if (mysql_new_select(lex, 0))
+ nest_level--;
+ if (mysql_new_select(this, 0, NULL))
return TRUE;
- mysql_init_select(lex);
- lex->current_select->linkage=UNION_TYPE;
+ mysql_init_select(this);
+ current_select->linkage= type;
if (is_union_distinct) /* UNION DISTINCT - remember position */
- lex->current_select->master_unit()->union_distinct=
- lex->current_select;
- return FALSE;
-}
-
-
-static bool add_create_index_prepare(LEX *lex, Table_ident *table)
-{
- lex->sql_command= SQLCOM_CREATE_INDEX;
- if (!lex->current_select->add_table_to_list(lex->thd, table, NULL,
- TL_OPTION_UPDATING,
- TL_READ_NO_INSERT,
- MDL_SHARED_UPGRADABLE))
- return TRUE;
- lex->alter_info.reset();
- lex->alter_info.flags= Alter_info::ALTER_ADD_INDEX;
- lex->option_list= NULL;
+ {
+ current_select->master_unit()->union_distinct=
+ current_select;
+ }
+ else
+ DBUG_ASSERT(type == UNION_TYPE);
return FALSE;
}
@@ -747,7 +591,7 @@ static bool add_create_index_prepare(LEX *lex, Table_ident *table)
@param no_lookahead True if the parser has no lookahead
*/
-static void sp_create_assignment_lex(THD *thd, bool no_lookahead)
+void sp_create_assignment_lex(THD *thd, bool no_lookahead)
{
LEX *lex= thd->lex;
@@ -785,7 +629,7 @@ static void sp_create_assignment_lex(THD *thd, bool no_lookahead)
@return false if success, true otherwise.
*/
-static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
+bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
{
LEX *lex= thd->lex;
@@ -838,50 +682,33 @@ static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
return false;
}
-
-static void add_key_to_list(LEX *lex, LEX_STRING *field_name,
- enum Key::Keytype type, bool check_exists)
+void LEX::add_key_to_list(LEX_CSTRING *field_name,
+ enum Key::Keytype type, bool check_exists)
{
Key *key;
- MEM_ROOT *mem_root= lex->thd->mem_root;
+ MEM_ROOT *mem_root= thd->mem_root;
key= new (mem_root)
- Key(type, null_lex_str, HA_KEY_ALG_UNDEF, false,
+ Key(type, &null_clex_str, HA_KEY_ALG_UNDEF, false,
DDL_options(check_exists ?
DDL_options::OPT_IF_NOT_EXISTS :
DDL_options::OPT_NONE));
- key->columns.push_back(new (mem_root) Key_part_spec(*field_name, 0),
+ key->columns.push_back(new (mem_root) Key_part_spec(field_name, 0),
mem_root);
- lex->alter_info.key_list.push_back(key, mem_root);
+ alter_info.key_list.push_back(key, mem_root);
}
-void LEX::init_last_field(Column_definition *field, const char *field_name,
- CHARSET_INFO *cs)
+void LEX::init_last_field(Column_definition *field,
+ const LEX_CSTRING *field_name,
+ const CHARSET_INFO *cs)
{
last_field= field;
- field->field_name= field_name;
+ field->field_name= *field_name;
/* reset LEX fields that are used in Create_field::set_and_check() */
charset= cs;
}
-void LEX::set_last_field_type(const Lex_field_type_st &type)
-{
- last_field->sql_type= type.field_type();
- last_field->charset= charset;
-
- if (type.length())
- {
- int err;
- last_field->length= my_strtoll10(type.length(), NULL, &err);
- if (err)
- last_field->length= ~0ULL; // safety
- }
- else
- last_field->length= 0;
-
- last_field->decimals= type.dec() ? (uint)atoi(type.dec()) : 0;
-}
bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
{
@@ -929,19 +756,33 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
ulong ulong_num;
ulonglong ulonglong_number;
longlong longlong_number;
+ uint sp_instr_addr;
/* structs */
- LEX_STRING lex_str;
+ LEX_CSTRING lex_str;
LEX_SYMBOL symbol;
+ Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable;
- struct { int vars, conds, hndlrs, curs; } spblock;
+ Lex_string_with_pos_st lex_string_with_pos;
+ Lex_spblock_st spblock;
+ Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type;
Lex_dyncol_type_st Lex_dyncol_type;
+ Lex_for_loop_st for_loop;
+ Lex_for_loop_bounds_st for_loop_bounds;
+ struct
+ {
+ LEX_CSTRING name;
+ uint offset;
+ } sp_cursor_name_and_offset;
/* pointers */
Create_field *create_field;
+ Spvar_definition *spvar_definition;
+ Row_definition_list *spvar_definition_list;
+ const Type_handler *type_handler;
CHARSET_INFO *charset;
Condition_information_item *cond_info_item;
DYNCALL_CREATE_DEF *dyncol_def;
@@ -951,25 +792,28 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
Item_param *item_param;
Key_part_spec *key_part;
LEX *lex;
- LEX_STRING *lex_str_ptr;
+ sp_assignment_lex *assignment_lex;
+ class sp_lex_cursor *sp_cursor_stmt;
+ LEX_CSTRING *lex_str_ptr;
LEX_USER *lex_user;
List<Condition_information_item> *cond_info_list;
List<DYNCALL_CREATE_DEF> *dyncol_def_list;
List<Item> *item_list;
+ List<sp_assignment_lex> *sp_assignment_lex_list;
List<Statement_information_item> *stmt_info_list;
List<String> *string_list;
- List<LEX_STRING> *lex_str_list;
+ List<LEX_CSTRING> *lex_str_list;
Statement_information_item *stmt_info_item;
String *string;
TABLE_LIST *table_list;
Table_ident *table;
+ Qualified_column_ident *qualified_column_ident;
char *simple_string;
const char *const_simple_string;
chooser_compare_func_creator boolfunc2creator;
class my_var *myvar;
class sp_condition_value *spcondvalue;
class sp_head *sphead;
- class sp_label *splabel;
class sp_name *spname;
class sp_variable *spvar;
class With_clause *with_clause;
@@ -984,6 +828,8 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
st_trg_execution_order trg_execution_order;
/* enums */
+ enum enum_view_suid view_suid;
+ enum sub_select_type unit_type;
enum Condition_information_item::Name cond_info_item_name;
enum enum_diag_condition_item_name diag_condition_item_name;
enum Diagnostics_information::Which_area diag_area;
@@ -992,7 +838,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
enum Item_udftype udf_type;
enum Key::Keytype key_type;
enum Statement_information_item::Name stmt_info_item_name;
- enum enum_field_types field_type;
enum enum_filetype filetype;
enum enum_tx_isolation tx_isolation;
enum enum_var_type var_type;
@@ -1112,6 +957,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CLASS_ORIGIN_SYM /* SQL-2003-N */
%token CLIENT_SYM
%token CLOSE_SYM /* SQL-2003-R */
+%token CLOB /* SQL-2003-R */
%token COALESCE /* SQL-2003-N */
%token CODE_SYM
%token COLLATE_SYM /* SQL-2003-R */
@@ -1157,6 +1003,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CURSOR_SYM /* SQL-2003-R */
%token CURSOR_NAME_SYM /* SQL-2003-N */
%token CURTIME /* MYSQL-FUNC */
+%token CYCLE_SYM
%token DATABASE
%token DATABASES
%token DATAFILE_SYM
@@ -1174,6 +1021,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DECIMAL_NUM
%token DECIMAL_SYM /* SQL-2003-R */
%token DECLARE_SYM /* SQL-2003-R */
+%token DECODE_SYM /* Oracle function, non-reserved */
%token DEFAULT /* SQL-2003-R */
%token DEFINER_SYM
%token DELAYED_SYM
@@ -1194,6 +1042,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DOUBLE_SYM /* SQL-2003-R */
%token DO_DOMAIN_IDS_SYM
%token DO_SYM
+%token DOT_DOT_SYM
%token DROP /* SQL-2003-R */
%token DUAL_SYM
%token DUMPFILE
@@ -1202,6 +1051,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EACH_SYM /* SQL-2003-R */
%token ELSE /* SQL-2003-R */
%token ELSEIF_SYM
+%token ELSIF_SYM /* Oracle, reserved in PL/SQL*/
%token ENABLE_SYM
%token ENCLOSED
%token END /* SQL-2003-R */
@@ -1220,8 +1070,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EVERY_SYM /* SQL-2003-N */
%token EXCHANGE_SYM
%token EXAMINED_SYM
+%token EXCEPT_SYM /* SQL-2003-R */
%token EXCLUDE_SYM /* SQL-2011-N */
%token EXECUTE_SYM /* SQL-2003-R */
+%token EXCEPTION_SYM /* SQL-2003-N */
%token EXISTS /* SQL-2003-R */
%token EXIT_SYM
%token EXPANSION_SYM
@@ -1259,6 +1111,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token GET_FORMAT /* MYSQL-FUNC */
%token GET_SYM /* SQL-2003-R */
%token GLOBAL_SYM /* SQL-2003-R */
+%token GOTO_SYM /* Oracle, reserved in PL/SQL*/
%token GRANT /* SQL-2003-R */
%token GRANTS
%token GROUP_SYM /* SQL-2003-R */
@@ -1289,6 +1142,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token IGNORE_SERVER_IDS_SYM
%token IMMEDIATE_SYM /* SQL-2003-R */
%token IMPORT
+%token INCREMENT_SYM
%token INDEXES
%token INDEX_SYM
%token INFILE
@@ -1299,6 +1153,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token INSERT /* SQL-2003-R */
%token INSERT_METHOD
%token INSTALL_SYM
+%token INTERSECT_SYM /* SQL-2003-R */
%token INTERVAL_SYM /* SQL-2003-R */
%token INTO /* SQL-2003-R */
%token INT_SYM /* SQL-2003-R */
@@ -1308,6 +1163,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token IPC_SYM
%token IS /* SQL-2003-R */
%token ISOLATION /* SQL-2003-R */
+%token ISOPEN_SYM /* Oracle-N */
%token ISSUER_SYM
%token ITERATE_SYM
%token JOIN_SYM /* SQL-2003-R */
@@ -1319,6 +1175,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token LANGUAGE_SYM /* SQL-2003-R */
%token LAST_SYM /* SQL-2003-N */
%token LAST_VALUE
+%token LASTVAL_SYM /* PostgreSQL sequence function */
%token LE /* OPERATOR */
%token LEADING /* SQL-2003-R */
%token LEAVES
@@ -1377,7 +1234,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_UPDATES_PER_HOUR
%token MAX_STATEMENT_TIME_SYM
%token MAX_USER_CONNECTIONS_SYM
-%token MAX_VALUE_SYM /* SQL-2003-N */
+%token MAXVALUE_SYM /* SQL-2003-N */
%token MEDIUMBLOB
%token MEDIUMINT
%token MEDIUMTEXT
@@ -1390,6 +1247,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MINUTE_MICROSECOND_SYM
%token MINUTE_SECOND_SYM
%token MINUTE_SYM /* SQL-2003-R */
+%token MINVALUE_SYM
%token MIN_ROWS
%token MIN_SYM /* SQL-2003-N */
%token MODE_SYM
@@ -1413,12 +1271,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NEG
%token NEW_SYM /* SQL-2003-R */
%token NEXT_SYM /* SQL-2003-N */
+%token NEXTVAL_SYM /* PostgreSQL sequence function */
+%token NOCACHE_SYM
+%token NOCYCLE_SYM
%token NODEGROUP_SYM
%token NONE_SYM /* SQL-2003-R */
%token NOT2_SYM
%token NOT_SYM /* SQL-2003-R */
+%token NOTFOUND_SYM /* Oracle-R */
%token NOW_SYM
%token NO_SYM /* SQL-2003-R */
+%token NOMAXVALUE_SYM
+%token NOMINVALUE_SYM
%token NO_WAIT_SYM
%token NO_WRITE_TO_BINLOG
%token NTILE_SYM
@@ -1428,6 +1292,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NUMERIC_SYM /* SQL-2003-R */
%token NTH_VALUE_SYM /* SQL-2011 */
%token NVARCHAR_SYM
+%token OF_SYM /* SQL-1992-R, Oracle-R */
%token OFFSET_SYM
%token OLD_PASSWORD_SYM
%token ON /* SQL-2003-R */
@@ -1475,6 +1340,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PREPARE_SYM /* SQL-2003-R */
%token PRESERVE_SYM
%token PREV_SYM
+%token PREVIOUS_SYM
%token PRIMARY_SYM /* SQL-2003-R */
%token PRIVILEGES /* SQL-2003-N */
%token PROCEDURE_SYM /* SQL-2003-R */
@@ -1487,8 +1353,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token QUARTER_SYM
%token QUERY_SYM
%token QUICK
+%token RAISE_SYM /* Oracle-PLSQL-R */
%token RANGE_SYM /* SQL-2003-R */
%token RANK_SYM
+%token RAW /* Oracle */
%token READS_SYM /* SQL-2003-R */
%token READ_ONLY_SYM
%token READ_SYM /* SQL-2003-N */
@@ -1519,6 +1387,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token REPLICATION
%token REQUIRE_SYM
%token RESET_SYM
+%token RESTART_SYM
%token RESIGNAL_SYM /* SQL-2003-R */
%token RESOURCES
%token RESTORE_SYM
@@ -1528,6 +1397,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RETURNING_SYM
%token RETURNS_SYM /* SQL-2003-R */
%token RETURN_SYM /* SQL-2003-R */
+%token REUSE_SYM /* Oracle-R */
%token REVERSE_SYM
%token REVOKE /* SQL-2003-R */
%token RIGHT /* SQL-2003-R */
@@ -1535,8 +1405,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ROLLBACK_SYM /* SQL-2003-R */
%token ROLLUP_SYM /* SQL-2003-R */
%token ROUTINE_SYM /* SQL-2003-N */
+%token ROWCOUNT_SYM /* Oracle-N */
%token ROW_SYM /* SQL-2003-R */
%token ROWS_SYM /* SQL-2003-R */
+%token ROWTYPE_SYM /* Oracle-PLSQL-R */
%token ROW_COUNT_SYM /* SQL-2003-N */
%token ROW_FORMAT_SYM
%token ROW_NUMBER_SYM
@@ -1550,12 +1422,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SELECT_SYM /* SQL-2003-R */
%token SENSITIVE_SYM /* FUTURE-USE */
%token SEPARATOR_SYM
+%token SEQUENCE_SYM
%token SERIALIZABLE_SYM /* SQL-2003-N */
%token SERIAL_SYM
%token SESSION_SYM /* SQL-2003-N */
%token SERVER_SYM
%token SERVER_OPTIONS
%token SET /* SQL-2003-R */
+%token SETVAL_SYM /* PostgreSQL sequence function */
%token SET_VAR
%token SHARE_SYM
%token SHIFT_LEFT /* OPERATOR */
@@ -1681,6 +1555,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token VALUE_SYM /* SQL-2003-R */
%token VARBINARY
%token VARCHAR /* SQL-2003-R */
+%token VARCHAR2 /* Oracle */
%token VARIABLES
%token VARIANCE_SYM
%token VARYING /* SQL-2003-R */
@@ -1733,35 +1608,52 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left INTERVAL_SYM
%type <lex_str>
- IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
+ IDENT IDENT_QUOTED DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
HEX_NUM HEX_STRING
- LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
+ LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
- NCHAR_STRING opt_component key_cache_name
+ opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident
+ sp_decl_ident
+ sp_block_label opt_place opt_db
+
+%type <lex_string_with_metadata>
+ TEXT_STRING
+ NCHAR_STRING
%type <lex_str_ptr>
opt_table_alias
+%type <lex_string_with_pos>
+ ident ident_with_tok_start
+
%type <table>
table_ident table_ident_nodb references xid
table_ident_opt_wild create_like
+%type <qualified_column_ident>
+ qualified_column_ident
+ optionally_qualified_column_ident
+
%type <simple_string>
- remember_name remember_end opt_db remember_tok_start
+ remember_name remember_end remember_tok_start
wild_and_where
- field_length opt_field_length opt_field_length_default_1
%type <const_simple_string>
- opt_place
+ field_length opt_field_length opt_field_length_default_1
%type <string>
text_string hex_or_bin_String opt_gconcat_separator
-%type <field_type> int_type real_type
+%type <type_handler> int_type real_type
%type <Lex_field_type> type_with_opt_collate field_type
+ field_type_numeric
+ field_type_string
+ field_type_lob
+ field_type_temporal
+ field_type_misc
%type <Lex_dyncol_type> opt_dyncol_type dyncol_type
numeric_dyncol_type temporal_dyncol_type string_dyncol_type
@@ -1788,7 +1680,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_recursive
%type <object_ddl_options>
- create_or_replace
+ create_or_replace
opt_if_not_exists
opt_if_exists
@@ -1810,11 +1702,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ws_nweights
ws_level_flag_desc ws_level_flag_reverse ws_level_flags
opt_ws_levels ws_level_list ws_level_list_item ws_level_number
- ws_level_range ws_level_list_or_range
+ ws_level_range ws_level_list_or_range bool
%type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number
+%type <longlong_number>
+ longlong_num
+
%type <choice> choice
%type <lock_type>
@@ -1830,7 +1725,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
geometry_function signed_literal expr_or_literal
opt_escape
sp_opt_default
- simple_ident_nospvar simple_ident_q
+ simple_ident_nospvar simple_ident_q simple_ident_q2
field_or_var limit_option
part_func_expr
window_func_expr
@@ -1853,6 +1748,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
expr_list opt_udf_expr_list udf_expr_list when_list
ident_list ident_list_arg opt_expr_list
+%type <sp_cursor_stmt>
+ sp_cursor_stmt_lex
+ sp_cursor_stmt
+
+%type <assignment_lex>
+ assignment_source_lex
+ assignment_source_expr
+
+%type <sp_assignment_lex_list>
+ cursor_actual_parameters
+ opt_parenthesized_cursor_actual_parameters
+
%type <var_type>
option_type opt_var_type opt_var_ident_type
@@ -1893,6 +1800,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <Lex_length_and_dec> precision opt_precision float_options
%type <symbol> keyword keyword_sp
+ keyword_sp_data_type
+ keyword_sp_not_data_type
%type <lex_user> user grant_user grant_role user_or_role current_role
admin_option_for_role user_maybe_role
@@ -1929,6 +1838,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <virtual_column> opt_check_constraint check_constraint virtual_column_func
column_default_expr
+%type <unit_type> unit_type_decl
%type <NONE>
analyze_stmt_command
@@ -1977,11 +1887,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
statement sp_suid
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
- view_algorithm view_or_trigger_or_sp_or_event
- definer_tail no_definer_tail
- view_suid view_tail view_list_opt view_list view_select
- view_check_option trigger_tail sp_tail sf_tail event_tail
- udf_tail udf_tail2
+ view_list_opt view_list view_select
+ trigger_tail sp_tail sf_tail event_tail
+ udf_tail create_function_tail
install uninstall partition_entry binlog_base64_event
normal_key_options normal_key_opts all_key_opt
spatial_key_options fulltext_key_options normal_key_opt
@@ -2010,13 +1918,15 @@ END_OF_INPUT
%type <NONE> case_stmt_specification
%type <NONE> loop_body while_body repeat_body
-%type <num> sp_decl_idents sp_handler_type sp_hcond_list
+%type <num> view_algorithm view_check_option
+%type <view_suid> view_suid opt_view_suid
+
+%type <num> sp_decl_idents sp_decl_idents_init_vars
+%type <num> sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
-%type <spblock> sp_decls sp_decl
-%type <lex> sp_cursor_stmt
+%type <spblock> sp_decls sp_decl sp_decl_body sp_decl_variable_list
%type <spname> sp_name
-%type <splabel> sp_block_content
-%type <spvar> sp_param_name_and_type
+%type <spvar> sp_param_name sp_param_name_and_type
%type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type
%type <num> index_hint_clause normal_join inner_join
@@ -2037,6 +1947,9 @@ END_OF_INPUT
%type <cond_info_item_name> condition_information_item_name;
%type <cond_info_list> condition_information;
+%type <spvar_definition> row_field_name row_field_definition
+%type <spvar_definition_list> row_field_definition_list row_type_body
+
%type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name
%type <NONE> opt_window_ref opt_window_frame_clause
@@ -2333,7 +2246,7 @@ master_def:
if ($3 > MASTER_DELAY_MAX)
{
my_error(ER_MASTER_DELAY_VALUE_OUT_OF_RANGE, MYF(0),
- $3, MASTER_DELAY_MAX);
+ (ulong) $3, (ulong) MASTER_DELAY_MAX);
}
else
Lex->mi.sql_delay = $3;
@@ -2513,7 +2426,7 @@ optional_connection_name:
/* empty */
{
LEX *lex= thd->lex;
- lex->mi.connection_name= null_lex_str;
+ lex->mi.connection_name= null_clex_str;
}
| connection_name
;
@@ -2549,7 +2462,7 @@ create:
*/
lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
lex->create_info.default_table_charset= NULL;
- lex->name= null_lex_str;
+ lex->name= null_clex_str;
lex->create_last_non_select_table= lex->last_table();
}
create_body
@@ -2568,13 +2481,71 @@ create:
}
create_table_set_open_action_and_adjust_tables(lex);
}
+ | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident
+ {
+ LEX *lex= thd->lex;
+ lex->create_info.init();
+ if (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, $1 | $4))
+ MYSQL_YYABORT;
+
+ if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
+ MYSQL_YYABORT;
+
+ /*
+ For CREATE TABLE, an non-existing table is not an error.
+ Instruct open_tables() to just take an MDL lock if the
+ table does not exist.
+ */
+ lex->alter_info.reset();
+ lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
+ lex->name= null_clex_str;
+ lex->create_last_non_select_table= lex->last_table();
+ if (!(lex->create_info.seq_create_info= new (thd->mem_root)
+ sequence_definition()))
+ MYSQL_YYABORT;
+ }
+ opt_sequence opt_create_table_options
+ {
+ LEX *lex= thd->lex;
+
+ if (lex->create_info.seq_create_info->check_and_adjust(1))
+ {
+ my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
+ lex->select_lex.table_list.first->db,
+ lex->select_lex.table_list.first->table_name);
+ MYSQL_YYABORT;
+ }
+
+ /* No fields specified, generate them */
+ if (prepare_sequence_fields(thd, &lex->alter_info.create_list))
+ MYSQL_YYABORT;
+
+ /* CREATE SEQUENCE always creates a sequence */
+ Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
+ Lex->create_info.sequence= 1;
+
+ lex->current_select= &lex->select_lex;
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
+ {
+ lex->create_info.use_default_db_type(thd);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
+ hton_name(lex->create_info.db_type)->str,
+ $5->table.str);
+ }
+ create_table_set_open_action_and_adjust_tables(lex);
+ }
| create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
opt_key_algorithm_clause
ON table_ident
{
- if (add_create_index_prepare(Lex, $8))
+ if (Lex->add_create_index_prepare($8))
MYSQL_YYABORT;
- if (Lex->add_create_index($2, $5, $6, $1 | $4))
+ if (Lex->add_create_index($2, &$5, $6, $1 | $4))
MYSQL_YYABORT;
}
'(' key_list ')' normal_key_options
@@ -2582,9 +2553,9 @@ create:
| create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
ON table_ident
{
- if (add_create_index_prepare(Lex, $7))
+ if (Lex->add_create_index_prepare($7))
MYSQL_YYABORT;
- if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $1 | $4))
+ if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
MYSQL_YYABORT;
}
'(' key_list ')' fulltext_key_options
@@ -2592,9 +2563,9 @@ create:
| create_or_replace spatial INDEX_SYM opt_if_not_exists ident
ON table_ident
{
- if (add_create_index_prepare(Lex, $7))
+ if (Lex->add_create_index_prepare($7))
MYSQL_YYABORT;
- if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $1 | $4))
+ if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
MYSQL_YYABORT;
}
'(' key_list ')' spatial_key_options
@@ -2611,15 +2582,50 @@ create:
MYSQL_YYABORT;
lex->name= $4;
}
- | create_or_replace
+ | create_or_replace definer_opt opt_view_suid VIEW_SYM
+ opt_if_not_exists table_ident
+ {
+ if (Lex->add_create_view(thd, $1 | $5,
+ DTYPE_ALGORITHM_UNDEFINED, $3, $6))
+ MYSQL_YYABORT;
+ }
+ view_list_opt AS view_select
+ { }
+ | create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM
+ opt_if_not_exists table_ident
+ {
+ if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7))
+ MYSQL_YYABORT;
+ }
+ view_list_opt AS view_select
+ { }
+ | create_or_replace definer_opt TRIGGER_SYM
+ { Lex->create_info.set($1); }
+ trigger_tail
+ { }
+ | create_or_replace definer_opt PROCEDURE_SYM
+ { Lex->create_info.set($1); }
+ sp_tail
+ { }
+ | create_or_replace definer_opt EVENT_SYM
+ { Lex->create_info.set($1); }
+ event_tail
+ { }
+ | create_or_replace definer FUNCTION_SYM
+ { Lex->create_info.set($1); }
+ sf_tail
+ { }
+ | create_or_replace no_definer FUNCTION_SYM
+ { Lex->create_info.set($1); }
+ create_function_tail
+ { }
+ | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
{
Lex->create_info.set($1);
- Lex->create_view_mode= ($1.or_replace() ? VIEW_CREATE_OR_REPLACE :
- VIEW_CREATE_NEW);
- Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
- Lex->create_view_suid= TRUE;
+ Lex->udf.type= UDFTYPE_AGGREGATE;
}
- view_or_trigger_or_sp_or_event { }
+ udf_tail
+ { }
| create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
opt_require_clause opt_resource_options
{
@@ -2645,6 +2651,107 @@ create:
{ }
;
+create_function_tail:
+ sf_tail { }
+ | udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; }
+ ;
+
+opt_sequence:
+ /* empty */ { }
+ | sequence_defs
+ ;
+
+sequence_defs:
+ sequence_def
+ | sequence_defs sequence_def
+ ;
+
+sequence_def:
+ MINVALUE_SYM opt_equal longlong_num
+ {
+ Lex->create_info.seq_create_info->min_value= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ }
+ | NO_SYM MINVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ }
+ | NOMINVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ }
+ | MAXVALUE_SYM opt_equal longlong_num
+ {
+ Lex->create_info.seq_create_info->max_value= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ }
+ | NO_SYM MAXVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ }
+ | NOMAXVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ }
+ | START_SYM opt_with longlong_num
+ {
+ Lex->create_info.seq_create_info->start= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_start;
+ }
+ | INCREMENT_SYM opt_by longlong_num
+ {
+ Lex->create_info.seq_create_info->increment= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_increment;
+ }
+ | CACHE_SYM opt_equal longlong_num
+ {
+ Lex->create_info.seq_create_info->cache= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
+ }
+ | NOCACHE_SYM
+ {
+ Lex->create_info.seq_create_info->cache= 0;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
+ }
+ | CYCLE_SYM
+ {
+ Lex->create_info.seq_create_info->cycle= 1;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
+ }
+ | NOCYCLE_SYM
+ {
+ Lex->create_info.seq_create_info->cycle= 0;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
+ }
+ | RESTART_SYM
+ {
+ if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
+ YYABORT;
+ }
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart;
+ }
+ | RESTART_SYM opt_with longlong_num
+ {
+ if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
+ YYABORT;
+ }
+ Lex->create_info.seq_create_info->restart= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart | seq_field_used_restart_value;
+ }
+ ;
+
server_def:
SERVER_SYM opt_if_not_exists ident_or_text
{
@@ -2672,7 +2779,8 @@ server_option:
{
MYSQL_YYABORT_UNLESS(Lex->server_options.host.str == 0);
Lex->server_options.host= $2;
- my_casedn_str(system_charset_info, Lex->server_options.host.str);
+ my_casedn_str(system_charset_info,
+ (char*) Lex->server_options.host.str);
}
| DATABASE TEXT_STRING_sys
{
@@ -2701,16 +2809,16 @@ server_option:
;
event_tail:
- remember_name EVENT_SYM opt_if_not_exists sp_name
+ remember_name opt_if_not_exists sp_name
{
LEX *lex=Lex;
lex->stmt_definition_begin= $1;
- if (lex->add_create_options_with_check($3))
+ if (lex->add_create_options_with_check($2))
MYSQL_YYABORT;
if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
- lex->event_parse_data->identifier= $4;
+ lex->event_parse_data->identifier= $3;
lex->event_parse_data->on_completion=
Event_parse_data::ON_COMPLETION_DROP;
@@ -2838,10 +2946,10 @@ ev_sql_stmt:
if (lex->sphead)
my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
- if (!make_sp_head(thd, lex->event_parse_data->identifier, TYPE_ENUM_PROCEDURE))
+ if (!lex->make_sp_head(thd, lex->event_parse_data->identifier,
+ TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
- lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
}
sp_proc_stmt
@@ -2874,29 +2982,13 @@ clear_privileges:
sp_name:
ident '.' ident
{
- if (!$1.str || check_db_name(&$1))
- my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
- if (check_routine_name(&$3))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) sp_name($1, $3, true);
- if ($$ == NULL)
+ if (!($$= Lex->make_sp_name(thd, &$1, &$3)))
MYSQL_YYABORT;
- $$->init_qname(thd);
}
| ident
{
- LEX *lex= thd->lex;
- LEX_STRING db;
- if (check_routine_name(&$1))
- {
+ if (!($$= Lex->make_sp_name(thd, &$1)))
MYSQL_YYABORT;
- }
- if (lex->copy_db_to(&db.str, &db.length))
- MYSQL_YYABORT;
- $$= new (thd->mem_root) sp_name(db, $1, false);
- if ($$ == NULL)
- MYSQL_YYABORT;
- $$->init_qname(thd);
}
;
@@ -2991,34 +3083,31 @@ sp_fdparams:
| sp_param_name_and_type
;
-sp_param_name_and_type:
+sp_param_name:
ident
{
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- if (spc->find_variable($1, TRUE))
- my_yyabort_error((ER_SP_DUP_PARAM, MYF(0), $1.str));
-
- sp_variable *spvar= spc->add_variable(thd, $1);
-
- lex->init_last_field(&spvar->field_def, $1.str,
- thd->variables.collation_database);
- $<spvar>$= spvar;
+ if (!($$= Lex->sp_param_init(&$1)))
+ MYSQL_YYABORT;
}
- type_with_opt_collate
- {
- LEX *lex= Lex;
- sp_variable *spvar= $<spvar>2;
+ ;
- if (lex->sphead->fill_field_definition(thd, lex, lex->last_field))
- {
+sp_param_name_and_type:
+ sp_param_name type_with_opt_collate
+ {
+ if (Lex->sp_param_fill_definition($$= $1))
MYSQL_YYABORT;
- }
- spvar->field_def.field_name= spvar->name.str;
- spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
-
- $$= spvar;
+ }
+ | sp_param_name TYPE_SYM OF_SYM qualified_column_ident
+ {
+ Lex->sphead->fill_spvar_using_type_reference($$= $1, $4);
+ }
+ | sp_param_name ROW_SYM row_type_body
+ {
+ $$= $1;
+ $$->field_def.field_name= $$->name;
+ Lex->sphead->fill_spvar_definition(thd, &$$->field_def);
+ Lex->sphead->row_fill_field_definitions(thd, $3);
+ $$->field_def.set_row_field_definitions($3);
}
;
@@ -3044,6 +3133,30 @@ sp_opt_inout:
| INOUT_SYM { $$= sp_variable::MODE_INOUT; }
;
+sp_parenthesized_fdparam_list:
+ '('
+ {
+ Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start() + 1;
+ }
+ sp_fdparam_list
+ ')'
+ {
+ Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
+ }
+ ;
+
+sp_parenthesized_pdparam_list:
+ '('
+ {
+ Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start() + 1;
+ }
+ sp_pdparam_list
+ ')'
+ {
+ Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
+ }
+ ;
+
sp_proc_stmts:
/* Empty */ {}
| sp_proc_stmts sp_proc_stmt ';'
@@ -3057,7 +3170,7 @@ sp_proc_stmts1:
sp_decls:
/* Empty */
{
- $$.vars= $$.conds= $$.hndlrs= $$.curs= 0;
+ $$.init();
}
| sp_decls sp_decl ';'
{
@@ -3065,196 +3178,194 @@ sp_decls:
because letting the grammar rules reflect it caused tricky
shift/reduce conflicts with the wrong result. (And we get
better error handling this way.) */
- if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
- my_yyabort_error((ER_SP_VARCOND_AFTER_CURSHNDLR, MYF(0)));
- if ($2.curs && $1.hndlrs)
- my_yyabort_error((ER_SP_CURSOR_AFTER_HANDLER, MYF(0)));
- $$.vars= $1.vars + $2.vars;
- $$.conds= $1.conds + $2.conds;
- $$.hndlrs= $1.hndlrs + $2.hndlrs;
- $$.curs= $1.curs + $2.curs;
+ if (Lex->sp_declarations_join(&$$, $1, $2))
+ MYSQL_YYABORT;
}
;
sp_decl:
- DECLARE_SYM sp_decl_idents
- {
- LEX *lex= Lex;
- sp_pcontext *pctx= lex->spcont;
+ DECLARE_SYM sp_decl_body { $$= $2; }
+ ;
- // get the last variable:
- uint num_vars= pctx->context_var_count();
- uint var_idx= pctx->var_context2runtime(num_vars - 1);
- sp_variable *spvar= pctx->find_variable(var_idx);
- lex->sphead->reset_lex(thd);
- pctx->declare_var_boundary($2);
- thd->lex->init_last_field(&spvar->field_def, spvar->name.str,
- thd->variables.collation_database);
+qualified_column_ident:
+ sp_decl_ident '.' ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(&$1, &$3)))
+ MYSQL_YYABORT;
}
- type_with_opt_collate
- sp_opt_default
+ | sp_decl_ident '.' ident '.' ident
{
- LEX *lex= Lex;
- sp_pcontext *pctx= lex->spcont;
- uint num_vars= pctx->context_var_count();
- Item *dflt_value_item= $5;
-
- if (!dflt_value_item)
- {
- dflt_value_item= new (thd->mem_root) Item_null(thd);
- if (dflt_value_item == NULL)
- MYSQL_YYABORT;
- /* QQ Set to the var_type with null_value? */
- }
-
- for (uint i = num_vars-$2 ; i < num_vars ; i++)
- {
- uint var_idx= pctx->var_context2runtime(i);
- sp_variable *spvar= pctx->find_variable(var_idx);
- bool last= i == num_vars - 1;
-
- if (!spvar)
- MYSQL_YYABORT;
-
- if (!last)
- spvar->field_def= *lex->last_field;
-
- spvar->default_value= dflt_value_item;
- spvar->field_def.field_name= spvar->name.str;
-
- if (lex->sphead->fill_field_definition(thd, lex,
- &spvar->field_def))
- {
- MYSQL_YYABORT;
- }
-
- spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
-
- /* The last instruction is responsible for freeing LEX. */
-
- sp_instr_set *is= new (lex->thd->mem_root)
- sp_instr_set(lex->sphead->instructions(),
- pctx, var_idx, dflt_value_item,
- $4.field_type(), lex, last);
- if (is == NULL || lex->sphead->add_instr(is))
- MYSQL_YYABORT;
- }
+ if (!($$= new (thd->mem_root) Qualified_column_ident(thd,
+ &$1, &$3, &$5)))
+ MYSQL_YYABORT;
+ }
+ ;
- pctx->declare_var_boundary(0);
- if (lex->sphead->restore_lex(thd))
+optionally_qualified_column_ident:
+ sp_decl_ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(&$1)))
MYSQL_YYABORT;
- $$.vars= $2;
- $$.conds= $$.hndlrs= $$.curs= 0;
}
- | DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond
+ | sp_decl_ident '.' ident
{
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- if (spc->find_condition($2, TRUE))
- my_yyabort_error((ER_SP_DUP_COND, MYF(0), $2.str));
- if(spc->add_condition(thd, $2, $5))
+ if (!($$= new (thd->mem_root) Qualified_column_ident(&$1, &$3)))
MYSQL_YYABORT;
- $$.vars= $$.hndlrs= $$.curs= 0;
- $$.conds= 1;
}
- | DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM
+ | sp_decl_ident '.' ident '.' ident
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
-
- sp_handler *h= lex->spcont->add_handler(thd,
- (sp_handler::enum_type) $2);
+ if (!($$= new (thd->mem_root) Qualified_column_ident(thd,
+ &$1, &$3, &$5)))
+ MYSQL_YYABORT;
+ }
+ ;
- lex->spcont= lex->spcont->push_context(thd,
- sp_pcontext::HANDLER_SCOPE);
+row_field_name:
+ ident
+ {
+ if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
+ system_charset_info, 1))
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
+ if (!($$= new (thd->mem_root) Spvar_definition()))
+ MYSQL_YYABORT;
+ Lex->init_last_field($$, &$1, thd->variables.collation_database);
+ }
+ ;
- sp_pcontext *ctx= lex->spcont;
- sp_instr_hpush_jump *i=
- new (thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
- ctx, h);
+row_field_definition:
+ row_field_name type_with_opt_collate
+ ;
- if (i == NULL || sp->add_instr(i))
+row_field_definition_list:
+ row_field_definition
+ {
+ if (!($$= new (thd->mem_root) Row_definition_list()))
MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | row_field_definition_list ',' row_field_definition
+ {
+ uint unused;
+ if ($1->find_row_field_by_name(&$3->field_name, &unused))
+ my_yyabort_error((ER_DUP_FIELDNAME, MYF(0), $3->field_name.str));
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+row_type_body:
+ '(' row_field_definition_list ')' { $$= $2; }
+ ;
+
+sp_decl_idents_init_vars:
+ sp_decl_idents
+ {
+ Lex->sp_variable_declarations_init(thd, $1);
+ }
+ ;
- /* For continue handlers, mark end of handler scope. */
- if ($2 == sp_handler::CONTINUE &&
- sp->push_backpatch(thd, i, ctx->last_label()))
+sp_decl_variable_list:
+ sp_decl_idents_init_vars
+ type_with_opt_collate
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_finalize(thd, $1,
+ &Lex->last_field[0], $3))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ TYPE_SYM OF_SYM optionally_qualified_column_ident
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $4, $5))
MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ ROW_SYM TYPE_SYM OF_SYM optionally_qualified_column_ident
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $5, $6))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ ROW_SYM row_type_body
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ ;
- if (sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0)))
+sp_decl_body:
+ sp_decl_variable_list
+ | sp_decl_ident CONDITION_SYM FOR_SYM sp_cond
+ {
+ if (Lex->spcont->declare_condition(thd, &$1, $4))
+ MYSQL_YYABORT;
+ $$.vars= $$.hndlrs= $$.curs= 0;
+ $$.conds= 1;
+ }
+ | sp_handler_type HANDLER_SYM FOR_SYM
+ {
+ if (Lex->sp_handler_declaration_init(thd, $1))
MYSQL_YYABORT;
}
sp_hcond_list sp_proc_stmt
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- sp_label *hlab= lex->spcont->pop_label(); /* After this hdlr */
- sp_instr_hreturn *i;
-
- if ($2 == sp_handler::CONTINUE)
- {
- i= new (thd->mem_root)
- sp_instr_hreturn(sp->instructions(), ctx);
- if (i == NULL ||
- sp->add_instr(i))
- MYSQL_YYABORT;
- }
- else
- { /* EXIT or UNDO handler, just jump to the end of the block */
- i= new (thd->mem_root)
- sp_instr_hreturn(sp->instructions(), ctx);
- if (i == NULL ||
- sp->add_instr(i) ||
- sp->push_backpatch(thd, i, lex->spcont->last_label())) /* Block end */
- MYSQL_YYABORT;
- }
- lex->sphead->backpatch(hlab);
-
- lex->spcont= ctx->pop_context();
-
+ if (Lex->sp_handler_declaration_finalize(thd, $1))
+ MYSQL_YYABORT;
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= 1;
}
- | DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
+ | sp_decl_ident CURSOR_SYM
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- uint offp;
- sp_instr_cpush *i;
-
- if (ctx->find_cursor($2, &offp, TRUE))
- my_yyabort_error((ER_SP_DUP_CURS, MYF(0), $2.str));
-
- i= new (thd->mem_root)
- sp_instr_cpush(sp->instructions(), ctx, $5,
- ctx->current_cursor_count());
- if (i == NULL || sp->add_instr(i) || ctx->add_cursor($2))
+ Lex->sp_block_init(thd);
+ }
+ opt_parenthesized_cursor_formal_parameters
+ FOR_SYM sp_cursor_stmt
+ {
+ sp_pcontext *param_ctx= Lex->spcont;
+ if (Lex->sp_block_finalize(thd))
+ MYSQL_YYABORT;
+ if (Lex->sp_declare_cursor(thd, &$1, $6, param_ctx, true))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
}
;
+opt_parenthesized_cursor_formal_parameters:
+ /* Empty */
+ | '(' sp_fdparams ')'
+ ;
+
+
+sp_cursor_stmt_lex:
+ {
+ DBUG_ASSERT(thd->lex->sphead);
+ if (!($$= new (thd->mem_root) sp_lex_cursor(thd, thd->lex)))
+ MYSQL_YYABORT;
+ }
+ ;
+
sp_cursor_stmt:
+ sp_cursor_stmt_lex
{
- Lex->sphead->reset_lex(thd);
+ DBUG_ASSERT(thd->free_list == NULL);
+ Lex->sphead->reset_lex(thd, $1);
}
select
{
- LEX *lex= Lex;
-
- DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT);
-
- if (lex->result)
- my_yyabort_error((ER_SP_BAD_CURSOR_SELECT, MYF(0)));
- lex->sp_lex_in_use= TRUE;
- $$= lex;
- if (lex->sphead->restore_lex(thd))
+ DBUG_ASSERT(Lex == $1);
+ if ($1->stmt_finalize(thd) ||
+ $1->sphead->restore_lex(thd))
MYSQL_YYABORT;
+ $$= $1;
}
;
@@ -3329,7 +3440,7 @@ sp_hcond:
}
| ident /* CONDITION name */
{
- $$= Lex->spcont->find_condition($1, false);
+ $$= Lex->spcont->find_condition(&$1, false);
if ($$ == NULL)
my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
}
@@ -3356,13 +3467,7 @@ sp_hcond:
signal_stmt:
SIGNAL_SYM signal_value opt_set_signal_information
{
- LEX *lex= thd->lex;
- Yacc_state *state= & thd->m_parser_state->m_yacc;
-
- lex->sql_command= SQLCOM_SIGNAL;
- lex->m_sql_cmd=
- new (thd->mem_root) Sql_cmd_signal($2, state->m_set_signal_info);
- if (lex->m_sql_cmd == NULL)
+ if (Lex->add_signal_statement(thd, $2))
MYSQL_YYABORT;
}
;
@@ -3376,7 +3481,7 @@ signal_value:
/* SIGNAL foo cannot be used outside of stored programs */
if (lex->spcont == NULL)
my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
- cond= lex->spcont->find_condition($1, false);
+ cond= lex->spcont->find_condition(&$1, false);
if (cond == NULL)
my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
if (cond->type != sp_condition_value::SQLSTATE)
@@ -3442,7 +3547,7 @@ signal_allowed_expr:
SIGNAL/RESIGNAL ...
SET <signal condition item name> = @foo := expr
*/
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -3483,14 +3588,7 @@ signal_condition_information_item_name:
resignal_stmt:
RESIGNAL_SYM opt_signal_value opt_set_signal_information
{
- LEX *lex= thd->lex;
- Yacc_state *state= & thd->m_parser_state->m_yacc;
-
- lex->sql_command= SQLCOM_RESIGNAL;
- lex->m_sql_cmd=
- new (thd->mem_root) Sql_cmd_resignal($2,
- state->m_set_signal_info);
- if (lex->m_sql_cmd == NULL)
+ if (Lex->add_resignal_statement(thd, $2))
MYSQL_YYABORT;
}
;
@@ -3559,15 +3657,15 @@ simple_target_specification:
ident
{
Lex_input_stream *lip= &thd->m_parser_state->m_lip;
- $$= create_item_for_sp_var(thd, $1, NULL,
- lip->get_tok_start(), lip->get_ptr());
-
+ $$= thd->lex->create_item_for_sp_var(&$1, NULL,
+ lip->get_tok_start(),
+ lip->get_ptr());
if ($$ == NULL)
MYSQL_YYABORT;
}
| '@' ident_or_text
{
- $$= new (thd->mem_root) Item_func_get_user_var(thd, $2);
+ $$= new (thd->mem_root) Item_func_get_user_var(thd, &$2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3641,17 +3739,21 @@ condition_information_item_name:
{ $$= Condition_information_item::RETURNED_SQLSTATE; }
;
+sp_decl_ident:
+ ident { $$= $1; }
+ ;
+
sp_decl_idents:
- ident
+ sp_decl_ident
{
/* NOTE: field definition is filled in sp_decl section. */
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_variable($1, TRUE))
+ if (spc->find_variable(&$1, TRUE))
my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $1.str));
- spc->add_variable(thd, $1);
+ spc->add_variable(thd, &$1);
$$= 1;
}
| sp_decl_idents ',' ident
@@ -3661,9 +3763,9 @@ sp_decl_idents:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_variable($3, TRUE))
+ if (spc->find_variable(&$3, TRUE))
my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $3.str));
- spc->add_variable(thd, $3);
+ spc->add_variable(thd, &$3);
$$= $1 + 1;
}
;
@@ -3710,7 +3812,7 @@ sp_proc_stmt_compound_ok:
sp_proc_stmt_if:
IF_SYM
{
- if (maybe_start_compound_statement(thd))
+ if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT;
Lex->sphead->new_cont_backpatch(NULL);
}
@@ -3785,7 +3887,7 @@ sp_proc_stmt_return:
i= new (thd->mem_root)
sp_instr_freturn(sp->instructions(), lex->spcont, $3,
- sp->m_return_field_def.sql_type, lex);
+ sp->m_return_field_def.type_handler(), lex);
if (i == NULL || sp->add_instr(i))
MYSQL_YYABORT;
sp->m_flags|= sp_head::HAS_RETURN;
@@ -3798,130 +3900,92 @@ sp_proc_stmt_return:
sp_proc_stmt_leave:
LEAVE_SYM label_ident
{
- LEX *lex= Lex;
- sp_head *sp = lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- sp_label *lab= ctx->find_label($2);
-
- if (! lab)
- my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str));
-
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
- /*
- When jumping to a BEGIN-END block end, the target jump
- points to the block hpop/cpop cleanup instructions,
- so we should exclude the block context here.
- When jumping to something else (i.e., SP_LAB_ITER),
- there are no hpop/cpop at the jump destination,
- so we should include the block context here for cleanup.
- */
- bool exclusive= (lab->type == sp_label::BEGIN);
-
- n= ctx->diff_handlers(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_hpop *hpop= new (thd->mem_root)
- sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(hpop);
- }
- n= ctx->diff_cursors(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_cpop *cpop= new (thd->mem_root)
- sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(cpop);
- }
- i= new (thd->mem_root) sp_instr_jump(ip, ctx);
- if (i == NULL)
+ if (Lex->sp_leave_statement(thd, &$2))
MYSQL_YYABORT;
- sp->push_backpatch(thd, i, lab); /* Jumping forward */
- sp->add_instr(i);
}
;
sp_proc_stmt_iterate:
ITERATE_SYM label_ident
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- sp_label *lab= ctx->find_label($2);
+ if (Lex->sp_iterate_statement(thd, &$2))
+ MYSQL_YYABORT;
+ }
+ ;
- if (! lab || lab->type != sp_label::ITERATION)
- my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str));
+assignment_source_lex:
+ {
+ DBUG_ASSERT(Lex->sphead);
+ if (!($$= new (thd->mem_root) sp_assignment_lex(thd, thd->lex)))
+ MYSQL_YYABORT;
+ }
+ ;
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
+assignment_source_expr:
+ assignment_source_lex
+ {
+ DBUG_ASSERT(thd->free_list == NULL);
+ Lex->sphead->reset_lex(thd, $1);
+ }
+ expr
+ {
+ DBUG_ASSERT($1 == thd->lex);
+ $$= $1;
+ $$->sp_lex_in_use= true;
+ $$->set_item_and_free_list($3, thd->free_list);
+ thd->free_list= NULL;
+ if ($$->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
- n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_hpop *hpop= new (thd->mem_root)
- sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL ||
- sp->add_instr(hpop))
- MYSQL_YYABORT;
- }
- n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_cpop *cpop= new (thd->mem_root)
- sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL ||
- sp->add_instr(cpop))
- MYSQL_YYABORT;
- }
- i= new (thd->mem_root)
- sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
- if (i == NULL ||
- sp->add_instr(i))
+cursor_actual_parameters:
+ assignment_source_expr
+ {
+ if (!($$= new (thd->mem_root) List<sp_assignment_lex>))
MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
}
+ | cursor_actual_parameters ',' assignment_source_expr
+ {
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+opt_parenthesized_cursor_actual_parameters:
+ /* Empty */ { $$= NULL; }
+ | '(' cursor_actual_parameters ')' { $$= $2; }
;
sp_proc_stmt_open:
- OPEN_SYM ident
+ OPEN_SYM ident opt_parenthesized_cursor_actual_parameters
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- uint offset;
- sp_instr_copen *i;
-
- if (! lex->spcont->find_cursor($2, &offset, false))
- my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
- i= new (thd->mem_root)
- sp_instr_copen(sp->instructions(), lex->spcont, offset);
- if (i == NULL ||
- sp->add_instr(i))
+ if (Lex->sp_open_cursor(thd, &$2, $3))
MYSQL_YYABORT;
}
;
-sp_proc_stmt_fetch:
- FETCH_SYM sp_opt_fetch_noise ident INTO
+sp_proc_stmt_fetch_head:
+ FETCH_SYM ident INTO
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- uint offset;
- sp_instr_cfetch *i;
-
- if (! lex->spcont->find_cursor($3, &offset, false))
- my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $3.str));
- i= new (thd->mem_root)
- sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
- if (i == NULL ||
- sp->add_instr(i))
+ if (Lex->sp_add_cfetch(thd, &$2))
MYSQL_YYABORT;
}
- sp_fetch_list
- {}
+ | FETCH_SYM FROM ident INTO
+ {
+ if (Lex->sp_add_cfetch(thd, &$3))
+ MYSQL_YYABORT;
+ }
+ | FETCH_SYM NEXT_SYM FROM ident INTO
+ {
+ if (Lex->sp_add_cfetch(thd, &$4))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_fetch:
+ sp_proc_stmt_fetch_head sp_fetch_list { }
;
sp_proc_stmt_close:
@@ -3932,7 +3996,7 @@ sp_proc_stmt_close:
uint offset;
sp_instr_cclose *i;
- if (! lex->spcont->find_cursor($2, &offset, false))
+ if (! lex->spcont->find_cursor(&$2, &offset, false))
my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
i= new (thd->mem_root)
sp_instr_cclose(sp->instructions(), lex->spcont, offset);
@@ -3942,12 +4006,6 @@ sp_proc_stmt_close:
}
;
-sp_opt_fetch_noise:
- /* Empty */
- | NEXT_SYM FROM
- | FROM
- ;
-
sp_fetch_list:
ident
{
@@ -3956,7 +4014,7 @@ sp_fetch_list:
sp_pcontext *spc= lex->spcont;
sp_variable *spv;
- if (!spc || !(spv = spc->find_variable($1, false)))
+ if (!spc || !(spv = spc->find_variable(&$1, false)))
my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
/* An SP local variable */
@@ -3970,7 +4028,7 @@ sp_fetch_list:
sp_pcontext *spc= lex->spcont;
sp_variable *spv;
- if (!spc || !(spv = spc->find_variable($3, false)))
+ if (!spc || !(spv = spc->find_variable(&$3, false)))
my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
/* An SP local variable */
@@ -3990,7 +4048,7 @@ sp_if:
sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, ctx, $2, lex);
if (i == NULL ||
- sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0)) ||
+ sp->push_backpatch(thd, i, ctx->push_label(thd, &empty_clex_str, 0)) ||
sp->add_cont_backpatch(i) ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -4007,7 +4065,7 @@ sp_if:
sp->add_instr(i))
MYSQL_YYABORT;
sp->backpatch(ctx->pop_label());
- sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0));
+ sp->push_backpatch(thd, i, ctx->push_label(thd, &empty_clex_str, 0));
}
sp_elseifs
{
@@ -4026,7 +4084,7 @@ sp_elseifs:
case_stmt_specification:
CASE_SYM
{
- if (maybe_start_compound_statement(thd))
+ if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT;
/**
@@ -4072,7 +4130,7 @@ case_stmt_specification:
BACKPATCH: Creating target label for the jump to after END CASE
(instruction 12 in the example)
*/
- Lex->spcont->push_label(thd, empty_lex_str, Lex->sphead->instructions());
+ Lex->spcont->push_label(thd, &empty_clex_str, Lex->sphead->instructions());
}
case_stmt_body
else_clause_opt
@@ -4097,7 +4155,7 @@ case_stmt_body:
{ Lex->sphead->reset_lex(thd); /* For expr $2 */ }
expr
{
- if (case_stmt_action_expr(Lex, $2))
+ if (Lex->case_stmt_action_expr($2))
MYSQL_YYABORT;
if (Lex->sphead->restore_lex(thd))
@@ -4129,7 +4187,7 @@ simple_when_clause:
/* Simple case: <caseval> = <whenval> */
LEX *lex= Lex;
- if (case_stmt_action_when(lex, $3, true))
+ if (lex->case_stmt_action_when($3, true))
MYSQL_YYABORT;
/* For expr $3 */
if (lex->sphead->restore_lex(thd))
@@ -4138,8 +4196,7 @@ simple_when_clause:
THEN_SYM
sp_proc_stmts1
{
- LEX *lex= Lex;
- if (case_stmt_action_then(lex))
+ if (Lex->case_stmt_action_then())
MYSQL_YYABORT;
}
;
@@ -4152,7 +4209,7 @@ searched_when_clause:
expr
{
LEX *lex= Lex;
- if (case_stmt_action_when(lex, $3, false))
+ if (lex->case_stmt_action_when($3, false))
MYSQL_YYABORT;
/* For expr $3 */
if (lex->sphead->restore_lex(thd))
@@ -4161,8 +4218,7 @@ searched_when_clause:
THEN_SYM
sp_proc_stmts1
{
- LEX *lex= Lex;
- if (case_stmt_action_then(lex))
+ if (Lex->case_stmt_action_then())
MYSQL_YYABORT;
}
;
@@ -4183,88 +4239,62 @@ else_clause_opt:
;
sp_opt_label:
- /* Empty */ { $$= null_lex_str; }
+ /* Empty */ { $$= null_clex_str; }
| label_ident { $$= $1; }
;
-sp_labeled_block:
- label_ident ':' BEGIN_SYM
+sp_block_label:
+ label_ident ':'
{
- LEX *lex= Lex;
- sp_pcontext *ctx= lex->spcont;
- sp_label *lab= ctx->find_label($1);
+ if (Lex->spcont->block_label_declare(&$1))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
- if (lab)
- my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str));
- lex->name= $1;
+sp_labeled_block:
+ sp_block_label
+ BEGIN_SYM
+ {
+ Lex->sp_block_init(thd, &$1);
}
- sp_block_content sp_opt_label
+ sp_decls
+ sp_proc_stmts
+ END
+ sp_opt_label
{
- if ($6.str)
- {
- if (my_strcasecmp(system_charset_info, $6.str, $5->name.str) != 0)
- my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $6.str));
- }
+ if (Lex->sp_block_finalize(thd, $4, &$7))
+ MYSQL_YYABORT;
}
;
sp_unlabeled_block:
BEGIN_SYM
{
- Lex->name= empty_lex_str; // Unlabeled blocks get an empty label
+ Lex->sp_block_init(thd);
}
- sp_block_content
- { }
- ;
-
-sp_unlabeled_block_not_atomic:
- BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
+ sp_decls
+ sp_proc_stmts
+ END
{
- if (maybe_start_compound_statement(thd))
+ if (Lex->sp_block_finalize(thd, $3))
MYSQL_YYABORT;
- Lex->name= empty_lex_str; // Unlabeled blocks get an empty label
}
- sp_block_content
- { }
;
-sp_block_content:
+sp_unlabeled_block_not_atomic:
+ BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
{
- LEX *lex= Lex;
- sp_label *lab= lex->spcont->push_label(thd, lex->name,
- lex->sphead->instructions());
- lab->type= sp_label::BEGIN;
- lex->spcont= lex->spcont->push_context(thd,
- sp_pcontext::REGULAR_SCOPE);
+ if (Lex->maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- sp_pcontext *ctx= lex->spcont;
- sp_instr *i;
-
- sp->backpatch(ctx->last_label()); /* We always have a label */
- if ($2.hndlrs)
- {
- i= new (thd->mem_root)
- sp_instr_hpop(sp->instructions(), ctx, $2.hndlrs);
- if (i == NULL ||
- sp->add_instr(i))
- MYSQL_YYABORT;
- }
- if ($2.curs)
- {
- i= new (thd->mem_root)
- sp_instr_cpop(sp->instructions(), ctx, $2.curs);
- if (i == NULL ||
- sp->add_instr(i))
- MYSQL_YYABORT;
- }
- lex->spcont= ctx->pop_context();
- $$ = lex->spcont->pop_label();
+ if (Lex->sp_block_finalize(thd, $5))
+ MYSQL_YYABORT;
}
;
@@ -4286,30 +4316,15 @@ while_body:
expr DO_SYM
{
LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- uint ip= sp->instructions();
- sp_instr_jump_if_not *i= new (thd->mem_root)
- sp_instr_jump_if_not(ip, lex->spcont, $1, lex);
- if (i == NULL ||
- /* Jumping forward */
- sp->push_backpatch(thd, i, lex->spcont->last_label()) ||
- sp->new_cont_backpatch(i) ||
- sp->add_instr(i))
+ if (lex->sp_while_loop_expression(thd, $1))
MYSQL_YYABORT;
- if (sp->restore_lex(thd))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
sp_proc_stmts1 END WHILE_SYM
{
- LEX *lex= Lex;
- uint ip= lex->sphead->instructions();
- sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i= new (thd->mem_root)
- sp_instr_jump(ip, lex->spcont, lab->ip);
- if (i == NULL ||
- lex->sphead->add_instr(i))
+ if (Lex->sp_while_loop_finalize(thd))
MYSQL_YYABORT;
- lex->sphead->do_cont_backpatch();
}
;
@@ -4333,79 +4348,68 @@ repeat_body:
}
;
-pop_sp_label:
+pop_sp_loop_label:
sp_opt_label
{
- sp_label *lab;
- Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
- if ($1.str)
- {
- if (my_strcasecmp(system_charset_info, $1.str,
- lab->name.str) != 0)
- my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $1.str));
- }
- }
- ;
-
-pop_sp_empty_label:
- {
- sp_label *lab;
- Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
- DBUG_ASSERT(lab->name.length == 0);
+ if (Lex->sp_pop_loop_label(thd, &$1))
+ MYSQL_YYABORT;
}
;
sp_labeled_control:
label_ident ':' LOOP_SYM
{
- if (push_sp_label(thd, $1))
+ if (Lex->sp_push_loop_label(thd, &$1))
MYSQL_YYABORT;
}
- loop_body pop_sp_label
+ loop_body pop_sp_loop_label
{ }
| label_ident ':' WHILE_SYM
{
- if (push_sp_label(thd, $1))
+ if (Lex->sp_push_loop_label(thd, &$1))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
}
- while_body pop_sp_label
+ while_body pop_sp_loop_label
{ }
| label_ident ':' REPEAT_SYM
{
- if (push_sp_label(thd, $1))
+ if (Lex->sp_push_loop_label(thd, &$1))
MYSQL_YYABORT;
}
- repeat_body pop_sp_label
+ repeat_body pop_sp_loop_label
{ }
;
sp_unlabeled_control:
LOOP_SYM
{
- if (push_sp_empty_label(thd))
+ if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
}
loop_body
- pop_sp_empty_label
- { }
+ {
+ Lex->sp_pop_loop_empty_label(thd);
+ }
| WHILE_SYM
{
- if (push_sp_empty_label(thd))
+ if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
}
while_body
- pop_sp_empty_label
- { }
+ {
+ Lex->sp_pop_loop_empty_label(thd);
+ }
| REPEAT_SYM
{
- if (push_sp_empty_label(thd))
+ if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
}
repeat_body
- pop_sp_empty_label
- { }
+ {
+ Lex->sp_pop_loop_empty_label(thd);
+ }
;
trg_action_time:
@@ -4762,11 +4766,11 @@ size_number:
ulonglong number;
uint text_shift_number= 0;
longlong prefix_number;
- char *start_ptr= $1.str;
+ const char *start_ptr= $1.str;
uint str_len= $1.length;
- char *end_ptr= start_ptr + str_len;
+ const char *end_ptr= start_ptr + str_len;
int error;
- prefix_number= my_strtoll10(start_ptr, &end_ptr, &error);
+ prefix_number= my_strtoll10(start_ptr, (char**) &end_ptr, &error);
if ((start_ptr + str_len - 1) == end_ptr)
{
switch (end_ptr[0])
@@ -4824,7 +4828,7 @@ create_body:
if (! src_table)
MYSQL_YYABORT;
/* CREATE TABLE ... LIKE is not allowed for views. */
- src_table->required_type= FRMTYPE_TABLE;
+ src_table->required_type= TABLE_TYPE_NORMAL;
}
;
@@ -4922,7 +4926,7 @@ have_partitioning:
/* empty */
{
#ifdef WITH_PARTITION_STORAGE_ENGINE
- LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
+ LEX_CSTRING partition_name={STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
my_yyabort_error((ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition"));
@@ -4939,7 +4943,7 @@ partition_entry:
LEX *lex= Lex;
if (!lex->part_info)
{
- my_parse_error(thd, ER_PARTITION_ENTRY_ERROR);
+ thd->parse_error(ER_PARTITION_ENTRY_ERROR);
MYSQL_YYABORT;
}
/*
@@ -4996,7 +5000,7 @@ opt_key_algo:
Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_55;
break;
default:
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -5112,7 +5116,7 @@ part_func_expr:
{
if (!Lex->safe_to_cache_query)
{
- my_parse_error(thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
+ thd->parse_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
MYSQL_YYABORT;
}
$$=$1;
@@ -5152,7 +5156,7 @@ part_defs:
if (part_info->num_parts !=
count_curr_parts)
{
- my_parse_error(thd, ER_PARTITION_WRONG_NO_PART_ERROR);
+ thd->parse_error(ER_PARTITION_WRONG_NO_PART_ERROR);
MYSQL_YYABORT;
}
}
@@ -5274,7 +5278,7 @@ opt_part_values:
;
part_func_max:
- MAX_VALUE_SYM
+ MAXVALUE_SYM
{
partition_info *part_info= Lex->part_info;
@@ -5282,7 +5286,7 @@ part_func_max:
part_info->num_columns != 1U)
{
part_info->print_debug("Kilroy II", NULL);
- my_parse_error(thd, ER_PARTITION_COLUMN_LIST_ERROR);
+ thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
MYSQL_YYABORT;
}
else
@@ -5313,7 +5317,7 @@ part_values_in:
part_info->num_columns > MAX_REF_PARTS)
{
part_info->print_debug("Kilroy III", NULL);
- my_parse_error(thd, ER_PARTITION_COLUMN_LIST_ERROR);
+ thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
MYSQL_YYABORT;
}
/*
@@ -5334,7 +5338,7 @@ part_values_in:
partition_info *part_info= Lex->part_info;
if (part_info->num_columns < 2U)
{
- my_parse_error(thd, ER_ROW_SINGLE_PARTITION_FIELD_ERROR);
+ thd->parse_error(ER_ROW_SINGLE_PARTITION_FIELD_ERROR);
MYSQL_YYABORT;
}
}
@@ -5375,7 +5379,7 @@ part_value_item:
error.
*/
part_info->print_debug("Kilroy I", NULL);
- my_parse_error(thd, ER_PARTITION_COLUMN_LIST_ERROR);
+ thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
MYSQL_YYABORT;
}
part_info->curr_list_object= 0;
@@ -5388,12 +5392,12 @@ part_value_item_list:
;
part_value_expr_item:
- MAX_VALUE_SYM
+ MAXVALUE_SYM
{
partition_info *part_info= Lex->part_info;
if (part_info->part_type == LIST_PARTITION)
{
- my_parse_error(thd, ER_MAXVALUE_IN_VALUES_IN);
+ thd->parse_error(ER_MAXVALUE_IN_VALUES_IN);
MYSQL_YYABORT;
}
if (part_info->add_max_value(thd))
@@ -5409,7 +5413,7 @@ part_value_expr_item:
if (!lex->safe_to_cache_query)
{
- my_parse_error(thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
+ thd->parse_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
MYSQL_YYABORT;
}
if (part_info->add_column_list_value(thd, part_expr))
@@ -5431,7 +5435,7 @@ opt_sub_partition:
We come here when we have defined subpartitions on the first
partition but not on all the subsequent partitions.
*/
- my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
}
@@ -5443,7 +5447,7 @@ opt_sub_partition:
if (part_info->num_subparts !=
part_info->count_curr_subparts)
{
- my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
}
@@ -5451,7 +5455,7 @@ opt_sub_partition:
{
if (part_info->partitions.elements > 1)
{
- my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
part_info->num_subparts= part_info->count_curr_subparts;
@@ -5486,7 +5490,7 @@ sub_part_definition:
the second partition (the current partition processed
have already been put into the partitions list.
*/
- my_parse_error(thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
MYSQL_YYABORT;
}
if (!sub_p_elem ||
@@ -5720,7 +5724,7 @@ create_table_option:
Lex->create_info.table_options|= HA_OPTION_PACK_KEYS;
break;
default:
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
@@ -5741,7 +5745,7 @@ create_table_option:
Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_ON;
break;
default:
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
@@ -5761,7 +5765,7 @@ create_table_option:
Lex->create_info.table_options|= HA_OPTION_STATS_PERSISTENT;
break;
default:
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
@@ -5784,7 +5788,7 @@ create_table_option:
we can store the higher bits from stats_sample_pages in .frm too. */
if ($3 == 0 || $3 > 0xffff)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
Lex->create_info.stats_sample_pages=$3;
@@ -5913,6 +5917,11 @@ create_table_option:
engine_option_value($1, &Lex->create_info.option_list,
&Lex->option_list_last);
}
+ | SEQUENCE_SYM opt_equal choice
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
+ Lex->create_info.sequence= $3;
+ }
;
default_charset:
@@ -6025,28 +6034,28 @@ key_def:
key_or_index opt_if_not_exists opt_ident opt_USING_key_algorithm
{
Lex->option_list= NULL;
- if (Lex->add_key(Key::MULTIPLE, $3, $4, $2))
+ if (Lex->add_key(Key::MULTIPLE, &$3, $4, $2))
MYSQL_YYABORT;
}
'(' key_list ')' normal_key_options { }
| key_or_index opt_if_not_exists ident TYPE_SYM btree_or_rtree
{
Lex->option_list= NULL;
- if (Lex->add_key(Key::MULTIPLE, $3, $5, $2))
+ if (Lex->add_key(Key::MULTIPLE, &$3, $5, $2))
MYSQL_YYABORT;
}
'(' key_list ')' normal_key_options { }
| fulltext opt_key_or_index opt_if_not_exists opt_ident
{
Lex->option_list= NULL;
- if (Lex->add_key($1, $4, HA_KEY_ALG_UNDEF, $3))
+ if (Lex->add_key($1, &$4, HA_KEY_ALG_UNDEF, $3))
MYSQL_YYABORT;
}
'(' key_list ')' fulltext_key_options { }
| spatial opt_key_or_index opt_if_not_exists opt_ident
{
Lex->option_list= NULL;
- if (Lex->add_key($1, $4, HA_KEY_ALG_UNDEF, $3))
+ if (Lex->add_key($1, &$4, HA_KEY_ALG_UNDEF, $3))
MYSQL_YYABORT;
}
'(' key_list ')' spatial_key_options { }
@@ -6055,7 +6064,7 @@ key_def:
opt_USING_key_algorithm
{
Lex->option_list= NULL;
- if (Lex->add_key($2, $4.str ? $4 : $1, $5, $3))
+ if (Lex->add_key($2, $4.str ? &$4 : &$1, $5, $3))
MYSQL_YYABORT;
}
'(' key_list ')' normal_key_options { }
@@ -6063,7 +6072,7 @@ key_def:
TYPE_SYM btree_or_rtree
{
Lex->option_list= NULL;
- if (Lex->add_key($2, $4.str ? $4 : $1, $6, $3))
+ if (Lex->add_key($2, $4.str ? &$4 : &$1, $6, $3))
MYSQL_YYABORT;
}
'(' key_list ')' normal_key_options { }
@@ -6071,7 +6080,7 @@ key_def:
{
if (Lex->check_add_key($4) ||
!(Lex->last_key= (new (thd->mem_root)
- Key(Key::MULTIPLE, $1.str ? $1 : $5,
+ Key(Key::MULTIPLE, $1.str ? &$1 : &$5,
HA_KEY_ALG_UNDEF, true, $4))))
MYSQL_YYABORT;
Lex->option_list= NULL;
@@ -6080,11 +6089,11 @@ key_def:
{
LEX *lex=Lex;
Key *key= (new (thd->mem_root)
- Foreign_key($5.str ? $5 : $1,
- lex->last_key->columns,
- $10->db,
- $10->table,
- lex->ref_list,
+ Foreign_key($5.str ? &$5 : &$1,
+ &lex->last_key->columns,
+ &$10->db,
+ &$10->table,
+ &lex->ref_list,
lex->fk_delete_opt,
lex->fk_update_opt,
lex->fk_match_option,
@@ -6130,7 +6139,7 @@ check_constraint:
;
opt_constraint:
- /* empty */ { $$= null_lex_str; }
+ /* empty */ { $$= null_clex_str; }
| constraint { $$= $1; }
;
@@ -6151,7 +6160,7 @@ field_spec:
if (!f)
MYSQL_YYABORT;
- lex->init_last_field(f, $1.str, NULL);
+ lex->init_last_field(f, &$1, NULL);
$<create_field>$= f;
}
field_type_or_serial opt_check_constraint
@@ -6168,19 +6177,18 @@ field_spec:
$$->create_if_not_exists= Lex->check_exists;
if ($$->flags & PRI_KEY_FLAG)
- add_key_to_list(lex, &$1, Key::PRIMARY, Lex->check_exists);
+ lex->add_key_to_list(&$1, Key::PRIMARY, lex->check_exists);
else if ($$->flags & UNIQUE_KEY_FLAG)
- add_key_to_list(lex, &$1, Key::UNIQUE, Lex->check_exists);
+ lex->add_key_to_list(&$1, Key::UNIQUE, lex->check_exists);
}
;
field_type_or_serial:
- field_type { Lex->set_last_field_type($1); } field_def
+ field_type { Lex->last_field->set_attributes($1, Lex->charset); }
+ field_def
| SERIAL_SYM
{
- Lex_field_type_st type;
- type.set(MYSQL_TYPE_LONGLONG);
- Lex->set_last_field_type(type);
+ Lex->last_field->set_handler(&type_handler_longlong);
Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG
| UNSIGNED_FLAG | UNIQUE_KEY_FLAG;
}
@@ -6319,65 +6327,86 @@ column_default_expr:
;
field_type:
+ field_type_numeric
+ | field_type_temporal
+ | field_type_string
+ | field_type_lob
+ | field_type_misc
+ ;
+
+field_type_numeric:
int_type opt_field_length field_options { $$.set($1, $2); }
| real_type opt_precision field_options { $$.set($1, $2); }
| FLOAT_SYM float_options field_options
{
- $$.set(MYSQL_TYPE_FLOAT, $2);
+ $$.set(&type_handler_float, $2);
if ($2.length() && !$2.dec())
{
int err;
ulonglong tmp_length= my_strtoll10($2.length(), NULL, &err);
if (err || tmp_length > PRECISION_FOR_DOUBLE)
my_yyabort_error((ER_WRONG_FIELD_SPEC, MYF(0),
- Lex->last_field->field_name));
+ Lex->last_field->field_name.str));
if (tmp_length > PRECISION_FOR_FLOAT)
- $$.set(MYSQL_TYPE_DOUBLE);
+ $$.set(&type_handler_double);
else
- $$.set(MYSQL_TYPE_FLOAT);
+ $$.set(&type_handler_float);
}
}
| BIT_SYM opt_field_length_default_1
{
- $$.set(MYSQL_TYPE_BIT, $2);
+ $$.set(&type_handler_bit, $2);
}
| BOOL_SYM
{
- $$.set(MYSQL_TYPE_TINY, "1");
+ $$.set(&type_handler_tiny, "1");
}
| BOOLEAN_SYM
{
- $$.set(MYSQL_TYPE_TINY, "1");
+ $$.set(&type_handler_tiny, "1");
}
- | char opt_field_length_default_1 opt_binary
+ | DECIMAL_SYM float_options field_options
+ { $$.set(&type_handler_newdecimal, $2);}
+ | NUMERIC_SYM float_options field_options
+ { $$.set(&type_handler_newdecimal, $2);}
+ | FIXED_SYM float_options field_options
+ { $$.set(&type_handler_newdecimal, $2);}
+ ;
+
+
+field_type_string:
+ char opt_field_length_default_1 opt_binary
{
- $$.set(MYSQL_TYPE_STRING, $2);
+ $$.set(&type_handler_string, $2);
}
| nchar opt_field_length_default_1 opt_bin_mod
{
- $$.set(MYSQL_TYPE_STRING, $2);
+ $$.set(&type_handler_string, $2);
bincmp_collation(national_charset_info, $3);
}
| BINARY opt_field_length_default_1
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_STRING, $2);
+ $$.set(&type_handler_string, $2);
}
| varchar field_length opt_binary
{
- $$.set(MYSQL_TYPE_VARCHAR, $2);
+ $$.set(&type_handler_varchar, $2);
}
| nvarchar field_length opt_bin_mod
{
- $$.set(MYSQL_TYPE_VARCHAR, $2);
+ $$.set(&type_handler_varchar, $2);
bincmp_collation(national_charset_info, $3);
}
| VARBINARY field_length
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_VARCHAR, $2);
+ $$.set(&type_handler_varchar, $2);
}
- | YEAR_SYM opt_field_length field_options
+ ;
+
+field_type_temporal:
+ YEAR_SYM opt_field_length field_options
{
if ($2)
{
@@ -6393,18 +6422,23 @@ field_type:
buff, "YEAR(4)");
}
}
- $$.set(MYSQL_TYPE_YEAR, $2);
+ $$.set(&type_handler_year, $2);
}
- | DATE_SYM
- { $$.set(MYSQL_TYPE_DATE); }
+ | DATE_SYM { $$.set(thd->type_handler_for_date()); }
| TIME_SYM opt_field_length
- { $$.set(opt_mysql56_temporal_format ?
- MYSQL_TYPE_TIME2 : MYSQL_TYPE_TIME, $2); }
+ {
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_time2) :
+ static_cast<const Type_handler*>(&type_handler_time),
+ $2);
+ }
| TIMESTAMP opt_field_length
{
if (thd->variables.sql_mode & MODE_MAXDB)
$$.set(opt_mysql56_temporal_format ?
- MYSQL_TYPE_DATETIME2 : MYSQL_TYPE_DATETIME, $2);
+ static_cast<const Type_handler*>(&type_handler_datetime2) :
+ static_cast<const Type_handler*>(&type_handler_datetime),
+ $2);
else
{
/*
@@ -6413,29 +6447,39 @@ field_type:
*/
if (!opt_explicit_defaults_for_timestamp)
Lex->last_field->flags|= NOT_NULL_FLAG;
- $$.set(opt_mysql56_temporal_format ? MYSQL_TYPE_TIMESTAMP2
- : MYSQL_TYPE_TIMESTAMP, $2);
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_timestamp2):
+ static_cast<const Type_handler*>(&type_handler_timestamp),
+ $2);
}
}
| DATETIME opt_field_length
- { $$.set(opt_mysql56_temporal_format ?
- MYSQL_TYPE_DATETIME2 : MYSQL_TYPE_DATETIME, $2); }
- | TINYBLOB
+ {
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_datetime2) :
+ static_cast<const Type_handler*>(&type_handler_datetime),
+ $2);
+ }
+ ;
+
+
+field_type_lob:
+ TINYBLOB
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_TINY_BLOB);
+ $$.set(&type_handler_tiny_blob);
}
| BLOB_SYM opt_field_length
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_BLOB, $2);
+ $$.set(&type_handler_blob, $2);
}
| spatial_type float_options srid_option
{
#ifdef HAVE_SPATIAL
Lex->charset=&my_charset_bin;
Lex->last_field->geom_type= $1;
- $$.set(MYSQL_TYPE_GEOMETRY, $2);
+ $$.set(&type_handler_geometry, $2);
#else
my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
sym_group_geom.needed_define));
@@ -6444,42 +6488,39 @@ field_type:
| MEDIUMBLOB
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_MEDIUM_BLOB);
+ $$.set(&type_handler_medium_blob);
}
| LONGBLOB
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_LONG_BLOB);
+ $$.set(&type_handler_long_blob);
}
| LONG_SYM VARBINARY
{
Lex->charset=&my_charset_bin;
- $$.set(MYSQL_TYPE_MEDIUM_BLOB);
+ $$.set(&type_handler_medium_blob);
}
| LONG_SYM varchar opt_binary
- { $$.set(MYSQL_TYPE_MEDIUM_BLOB); }
+ { $$.set(&type_handler_medium_blob); }
| TINYTEXT opt_binary
- { $$.set(MYSQL_TYPE_TINY_BLOB); }
+ { $$.set(&type_handler_tiny_blob); }
| TEXT_SYM opt_field_length opt_binary
- { $$.set(MYSQL_TYPE_BLOB, $2); }
+ { $$.set(&type_handler_blob, $2); }
| MEDIUMTEXT opt_binary
- { $$.set(MYSQL_TYPE_MEDIUM_BLOB); }
+ { $$.set(&type_handler_medium_blob); }
| LONGTEXT opt_binary
- { $$.set(MYSQL_TYPE_LONG_BLOB); }
- | DECIMAL_SYM float_options field_options
- { $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
- | NUMERIC_SYM float_options field_options
- { $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
- | FIXED_SYM float_options field_options
- { $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
- | ENUM '(' string_list ')' opt_binary
- { $$.set(MYSQL_TYPE_ENUM); }
- | SET '(' string_list ')' opt_binary
- { $$.set(MYSQL_TYPE_SET); }
+ { $$.set(&type_handler_long_blob); }
| LONG_SYM opt_binary
- { $$.set(MYSQL_TYPE_MEDIUM_BLOB); }
+ { $$.set(&type_handler_medium_blob); }
| JSON_SYM opt_binary
- { $$.set(MYSQL_TYPE_BLOB); }
+ { $$.set(&type_handler_blob); }
+ ;
+
+field_type_misc:
+ ENUM '(' string_list ')' opt_binary
+ { $$.set(&type_handler_enum); }
+ | SET '(' string_list ')' opt_binary
+ { $$.set(&type_handler_set); }
;
spatial_type:
@@ -6516,23 +6557,22 @@ nvarchar:
;
int_type:
- INT_SYM { $$=MYSQL_TYPE_LONG; }
- | TINYINT { $$=MYSQL_TYPE_TINY; }
- | SMALLINT { $$=MYSQL_TYPE_SHORT; }
- | MEDIUMINT { $$=MYSQL_TYPE_INT24; }
- | BIGINT { $$=MYSQL_TYPE_LONGLONG; }
+ INT_SYM { $$= &type_handler_long; }
+ | TINYINT { $$= &type_handler_tiny; }
+ | SMALLINT { $$= &type_handler_short; }
+ | MEDIUMINT { $$= &type_handler_int24; }
+ | BIGINT { $$= &type_handler_longlong; }
;
real_type:
REAL
{
$$= thd->variables.sql_mode & MODE_REAL_AS_FLOAT ?
- MYSQL_TYPE_FLOAT : MYSQL_TYPE_DOUBLE;
+ static_cast<const Type_handler *>(&type_handler_float) :
+ static_cast<const Type_handler *>(&type_handler_double);
}
- | DOUBLE_SYM
- { $$=MYSQL_TYPE_DOUBLE; }
- | DOUBLE_SYM PRECISION
- { $$=MYSQL_TYPE_DOUBLE; }
+ | DOUBLE_SYM { $$= &type_handler_double; }
+ | DOUBLE_SYM PRECISION { $$= &type_handler_double; }
;
srid_option:
@@ -6676,7 +6716,7 @@ type_with_opt_collate:
if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))
MYSQL_YYABORT;
}
- Lex->set_last_field_type($1);
+ Lex->last_field->set_attributes($1, Lex->charset);
}
;
@@ -6770,7 +6810,7 @@ ws_nweights:
{
if ($2 == 0)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -6858,14 +6898,14 @@ opt_ref_list:
ref_list:
ref_list ',' ident
{
- Key_part_spec *key= new (thd->mem_root) Key_part_spec($3, 0);
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec(&$3, 0);
if (key == NULL)
MYSQL_YYABORT;
Lex->ref_list.push_back(key, thd->mem_root);
}
| ident
{
- Key_part_spec *key= new (thd->mem_root) Key_part_spec($1, 0);
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec(&$1, 0);
if (key == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
@@ -7091,7 +7131,7 @@ key_list:
key_part:
ident
{
- $$= new (thd->mem_root) Key_part_spec($1, 0);
+ $$= new (thd->mem_root) Key_part_spec(&$1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7100,19 +7140,19 @@ key_part:
int key_part_len= atoi($3.str);
if (!key_part_len)
my_yyabort_error((ER_KEY_PART_0, MYF(0), $1.str));
- $$= new (thd->mem_root) Key_part_spec($1, (uint) key_part_len);
+ $$= new (thd->mem_root) Key_part_spec(&$1, (uint) key_part_len);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
opt_ident:
- /* empty */ { $$= null_lex_str; }
+ /* empty */ { $$= null_clex_str; }
| field_ident { $$= $1; }
;
opt_component:
- /* empty */ { $$= null_lex_str; }
+ /* empty */ { $$= null_clex_str; }
| '.' ident { $$= $2; }
;
@@ -7129,8 +7169,8 @@ string_list:
alter:
ALTER
{
- Lex->name= null_lex_str;
- Lex->only_view= FALSE;
+ Lex->name= null_clex_str;
+ Lex->table_type= TABLE_TYPE_UNKNOWN;
Lex->sql_command= SQLCOM_ALTER_TABLE;
Lex->duplicates= DUP_ERROR;
Lex->select_lex.init_order();
@@ -7189,7 +7229,7 @@ alter:
if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
- bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ lex->sp_chistics.init();
}
sp_a_chistics
{
@@ -7204,7 +7244,7 @@ alter:
if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
- bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+ lex->sp_chistics.init();
}
sp_a_chistics
{
@@ -7213,31 +7253,24 @@ alter:
lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->spname= $3;
}
- | ALTER view_algorithm definer_opt
+ | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident
{
- LEX *lex= Lex;
-
- if (lex->sphead)
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
- lex->create_view_mode= VIEW_ALTER;
+ if (Lex->add_alter_view(thd, $2, $4, $6))
+ MYSQL_YYABORT;
}
- view_tail
+ view_list_opt AS view_select
{}
- | ALTER definer_opt
+ | ALTER definer_opt opt_view_suid VIEW_SYM table_ident
/*
We have two separate rules for ALTER VIEW rather that
optional view_algorithm above, to resolve the ambiguity
with the ALTER EVENT below.
*/
{
- LEX *lex= Lex;
-
- if (lex->sphead)
- my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
- lex->create_view_algorithm= VIEW_ALGORITHM_INHERIT;
- lex->create_view_mode= VIEW_ALTER;
+ if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
+ MYSQL_YYABORT;
}
- view_tail
+ view_list_opt AS view_select
{}
| ALTER definer_opt remember_name EVENT_SYM sp_name
{
@@ -7264,7 +7297,7 @@ alter:
{
if (!($7 || $8 || $9 || $10 || $11))
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
/*
@@ -7307,6 +7340,33 @@ alter:
Lex->create_info.set($2);
Lex->sql_command= SQLCOM_ALTER_USER;
}
+ | ALTER SEQUENCE_SYM opt_if_exists_table_element
+ {
+ LEX *lex= Lex;
+ lex->name= null_clex_str;
+ lex->table_type= TABLE_TYPE_UNKNOWN;
+ lex->sql_command= SQLCOM_ALTER_SEQUENCE;
+ lex->create_info.init();
+ lex->no_write_to_binlog= 0;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ }
+ table_ident
+ {
+ LEX *lex= Lex;
+ if (!(lex->create_info.seq_create_info= new (thd->mem_root)
+ sequence_definition()) ||
+ !lex->select_lex.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE, MDL_EXCLUSIVE))
+ MYSQL_YYABORT;
+ }
+ sequence_defs
+ {
+ /* Create a generic ALTER SEQUENCE statment. */
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence();
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
;
ev_alter_on_schedule_completion:
@@ -7335,7 +7395,7 @@ opt_ev_sql_stmt:
;
ident_or_empty:
- /* empty */ { $$= null_lex_str; }
+ /* empty */ { $$= null_clex_str; }
| ident { $$= $1; }
;
@@ -7620,7 +7680,7 @@ alter_list_item:
{
Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
Lex->create_last_non_select_table= Lex->last_table();
- $5->change= $4.str;
+ $5->change= $4;
$5->after= $6;
}
| MODIFY_SYM opt_column opt_if_exists_table_element
@@ -7725,7 +7785,7 @@ alter_list_item:
MYSQL_YYABORT;
}
if (check_table_name($3->table.str,$3->table.length, FALSE) ||
- ($3->db.str && check_db_name(&$3->db)))
+ ($3->db.str && check_db_name((LEX_STRING*) &$3->db)))
my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3->table.str));
lex->name= $3->table;
lex->alter_info.flags|= Alter_info::ALTER_RENAME;
@@ -7840,15 +7900,16 @@ opt_restrict:
;
opt_place:
- /* empty */ { $$= NULL; }
+ /* empty */ { $$= null_clex_str; }
| AFTER_SYM ident
{
- $$= $2.str;
+ $$= $2;
Lex->alter_info.flags |= Alter_info::ALTER_COLUMN_ORDER;
}
| FIRST_SYM
{
- $$= first_keyword;
+ $$.str= first_keyword;
+ $$.length= 5; /* Length of "first" */
Lex->alter_info.flags |= Alter_info::ALTER_COLUMN_ORDER;
}
;
@@ -7903,7 +7964,7 @@ start:
if (($3 & MYSQL_START_TRANS_OPT_READ_WRITE) &&
($3 & MYSQL_START_TRANS_OPT_READ_ONLY))
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
lex->start_transaction_opt= $3;
@@ -8006,7 +8067,9 @@ opt_checksum_type:
repair_table_or_view:
table_or_tables table_list opt_mi_repair_type
- | VIEW_SYM { Lex->only_view= TRUE; } table_list opt_view_repair_type
+ | VIEW_SYM
+ { Lex->table_type= TABLE_TYPE_VIEW; }
+ table_list opt_view_repair_type
;
repair:
@@ -8171,7 +8234,9 @@ binlog_base64_event:
check_view_or_table:
table_or_tables table_list opt_mi_check_type
- | VIEW_SYM { Lex->only_view= TRUE; } table_list opt_view_check_type
+ | VIEW_SYM
+ { Lex->table_type= TABLE_TYPE_VIEW; }
+ table_list opt_view_check_type
;
check: CHECK_SYM
@@ -8718,7 +8783,7 @@ select_item_list:
{
Item *item= new (thd->mem_root)
Item_field(thd, &thd->lex->current_select->context,
- NULL, NULL, "*");
+ NULL, NULL, &star_clex_str);
if (item == NULL)
MYSQL_YYABORT;
if (add_item_to_list(thd, item))
@@ -8747,7 +8812,7 @@ select_item:
$2->is_autogenerated_name= FALSE;
$2->set_name(thd, $4.str, $4.length, system_charset_info);
}
- else if (!$2->name)
+ else if (!$2->name.str || $2->name.str == item_empty_name)
{
$2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
}
@@ -8768,12 +8833,12 @@ remember_name:
remember_end:
{
- $$= (char*) YYLIP->get_cpp_tok_end();
+ $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
}
;
select_alias:
- /* empty */ { $$=null_lex_str;}
+ /* empty */ { $$=null_clex_str;}
| AS ident { $$=$2; }
| AS TEXT_STRING_sys { $$=$2; }
| ident { $$=$1; }
@@ -9372,10 +9437,7 @@ column_default_non_parenthesized_expr:
}
| CAST_SYM '(' expr AS cast_type ')'
{
- LEX *lex= Lex;
- $$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
- lex->charset);
- if ($$ == NULL)
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CASE_SYM opt_expr when_list opt_else END
@@ -9386,9 +9448,7 @@ column_default_non_parenthesized_expr:
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
- $$= create_func_cast(thd, $3, $5.type(), $5.length(), $5.dec(),
- Lex->charset);
- if ($$ == NULL)
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
@@ -9414,6 +9474,41 @@ column_default_non_parenthesized_expr:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | NEXT_SYM VALUE_SYM FOR_SYM table_ident
+ {
+ if (!($$= Lex->create_item_func_nextval(thd, $4)))
+ MYSQL_YYABORT;
+ }
+ | NEXTVAL_SYM '(' table_ident ')'
+ {
+ if (!($$= Lex->create_item_func_nextval(thd, $3)))
+ MYSQL_YYABORT;
+ }
+ | PREVIOUS_SYM VALUE_SYM FOR_SYM table_ident
+ {
+ if (!($$= Lex->create_item_func_lastval(thd, $4)))
+ MYSQL_YYABORT;
+ }
+ | LASTVAL_SYM '(' table_ident ')'
+ {
+ if (!($$= Lex->create_item_func_lastval(thd, $3)))
+ MYSQL_YYABORT;
+ }
+ | SETVAL_SYM '(' table_ident ',' longlong_num ')'
+ {
+ if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, 1)))
+ MYSQL_YYABORT;
+ }
+ | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ')'
+ {
+ if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, $7)))
+ MYSQL_YYABORT;
+ }
+ | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ',' ulonglong_num ')'
+ {
+ if (!($$= Lex->create_item_func_setval(thd, $3, $5, $9, $7)))
+ MYSQL_YYABORT;
+ }
;
simple_expr:
@@ -9432,9 +9527,8 @@ simple_expr:
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
{
- $$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
- &my_charset_bin);
- if ($$ == NULL)
+ Type_cast_attributes at(&my_charset_bin);
+ if (!($$= type_handler_long_blob.create_typecast_item(thd, $2, at)))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
@@ -9728,6 +9822,12 @@ function_call_nonkeyword:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | DECODE_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_decode(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
| EXTRACT_SYM '(' interval FROM expr ')'
{
$$=new (thd->mem_root) Item_extract(thd, $3, $5);
@@ -9873,7 +9973,7 @@ function_call_nonkeyword:
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
- $$= create_func_dyncol_get(thd, $3, $5, $7.type(),
+ $$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
$7.length(), $7.dec(),
lex->charset);
if ($$ == NULL)
@@ -10157,7 +10257,7 @@ function_call_generic:
{
if (lex->current_select->inc_in_sum_expr())
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -10184,10 +10284,10 @@ function_call_generic:
This will be revised with WL#2128 (SQL PATH)
*/
- builder= find_native_function_builder(thd, $1);
+ builder= find_native_function_builder(thd, &$1);
if (builder)
{
- item= builder->create_func(thd, $1, $4);
+ item= builder->create_func(thd, &$1, $4);
}
else
{
@@ -10209,7 +10309,7 @@ function_call_generic:
{
builder= find_qualified_function_builder(thd);
DBUG_ASSERT(builder);
- item= builder->create_func(thd, $1, $4);
+ item= builder->create_func(thd, &$1, $4);
}
}
@@ -10237,7 +10337,7 @@ function_call_generic:
version() (a vendor can specify any schema).
*/
- if (!$1.str || check_db_name(&$1))
+ if (!$1.str || check_db_name((LEX_STRING*) &$1))
my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
{
@@ -10246,7 +10346,7 @@ function_call_generic:
builder= find_qualified_function_builder(thd);
DBUG_ASSERT(builder);
- item= builder->create_with_db(thd, $1, $3, true, $5);
+ item= builder->create_with_db(thd, &$1, &$3, true, $5);
if (! ($$= item))
{
@@ -10598,7 +10698,7 @@ simple_window_func:
window_name:
ident
{
- $$= (LEX_STRING *) thd->memdup(&$1, sizeof(LEX_STRING));
+ $$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10620,7 +10720,7 @@ variable_aux:
ident_or_text SET_VAR expr
{
Item_func_set_user_var *item;
- $$= item= new (thd->mem_root) Item_func_set_user_var(thd, $1, $3);
+ $$= item= new (thd->mem_root) Item_func_set_user_var(thd, &$1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
@@ -10629,7 +10729,7 @@ variable_aux:
}
| ident_or_text
{
- $$= new (thd->mem_root) Item_func_get_user_var(thd, $1);
+ $$= new (thd->mem_root) Item_func_get_user_var(thd, &$1);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
@@ -10640,7 +10740,7 @@ variable_aux:
/* disallow "SELECT @@global.global.variable" */
if ($3.str && $4.str && check_reserved_words(&$3))
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
if (!($$= get_system_var(thd, $2, $3, $4)))
@@ -10683,7 +10783,7 @@ in_sum_expr:
LEX *lex= Lex;
if (lex->current_select->inc_in_sum_expr())
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -10696,34 +10796,34 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
- { $$.set(ITEM_CAST_CHAR, $2); Lex->charset= &my_charset_bin; }
+ { $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
| CHAR_SYM opt_field_length
{ Lex->charset= thd->variables.collation_connection; }
opt_binary
- { $$.set(ITEM_CAST_CHAR, $2); }
+ { $$.set(&type_handler_long_blob, $2); }
| NCHAR_SYM opt_field_length
{
Lex->charset= national_charset_info;
- $$.set(ITEM_CAST_CHAR, $2, 0);
+ $$.set(&type_handler_long_blob, $2, 0);
}
| cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; }
;
cast_type_numeric:
- INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | SIGNED_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | SIGNED_SYM INT_SYM { $$.set(ITEM_CAST_SIGNED_INT); }
- | UNSIGNED { $$.set(ITEM_CAST_UNSIGNED_INT); }
- | UNSIGNED INT_SYM { $$.set(ITEM_CAST_UNSIGNED_INT); }
- | DECIMAL_SYM float_options { $$.set(ITEM_CAST_DECIMAL, $2); }
- | DOUBLE_SYM opt_precision { $$.set(ITEM_CAST_DOUBLE, $2); }
+ INT_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM INT_SYM { $$.set(&type_handler_longlong); }
+ | UNSIGNED { $$.set(&type_handler_ulonglong); }
+ | UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
+ | DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
+ | DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;
cast_type_temporal:
- DATE_SYM { $$.set(ITEM_CAST_DATE); }
- | TIME_SYM opt_field_length { $$.set(ITEM_CAST_TIME, 0, $2); }
- | DATETIME opt_field_length { $$.set(ITEM_CAST_DATETIME, 0, $2); }
+ DATE_SYM { $$.set(&type_handler_newdate); }
+ | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
+ | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
;
opt_expr_list:
@@ -10802,7 +10902,7 @@ table_ref:
LEX *lex= Lex;
if (!($$= lex->current_select->nest_last_join(thd)))
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -11057,6 +11157,7 @@ table_primary_derived:
are no outer parentheses, add_table_to_list() will throw
error in this case */
LEX *lex=Lex;
+ lex->check_automatic_up(UNSPECIFIED_TYPE);
SELECT_LEX *sel= lex->current_select;
SELECT_LEX_UNIT *unit= sel->master_unit();
lex->current_select= sel= unit->outer_select();
@@ -11072,17 +11173,13 @@ table_primary_derived:
lex->pop_context();
lex->nest_level--;
}
- /*else if (($3->select_lex &&
- $3->select_lex->master_unit()->is_union() &&
- ($3->select_lex->master_unit()->first_select() ==
- $3->select_lex || !$3->lifted)) || $5)*/
else if ($5 != NULL)
{
/*
Tables with or without joins within parentheses cannot
have aliases, and we ruled out derived tables above.
*/
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
else
@@ -11147,7 +11244,7 @@ select_derived_union:
{
if ($1)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -11155,7 +11252,7 @@ select_derived_union:
{
if ($1)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -11211,7 +11308,7 @@ select_derived:
MYSQL_YYABORT;
if (!$2 && $$)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -11238,11 +11335,11 @@ select_derived2:
if (!lex->expr_allows_subselect ||
lex->sql_command == (int)SQLCOM_PURGE)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
- mysql_new_select(lex, 1))
+ mysql_new_select(lex, 1, NULL))
MYSQL_YYABORT;
mysql_init_select(lex);
lex->current_select->linkage= DERIVED_TABLE_TYPE;
@@ -11336,7 +11433,7 @@ key_usage_element:
ident
{ Select->add_index_hint(thd, $1.str, $1.length); }
| PRIMARY_SYM
- { Select->add_index_hint(thd, (char *)"PRIMARY", 7); }
+ { Select->add_index_hint(thd, "PRIMARY", 7); }
;
key_usage_list:
@@ -11412,7 +11509,7 @@ opt_table_alias:
/* empty */ { $$=0; }
| table_alias ident
{
- $$= (LEX_STRING*) thd->memdup(&$2,sizeof(LEX_STRING));
+ $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -11548,7 +11645,7 @@ window_def:
if (Select->add_window_def(thd, $1, lex->win_ref,
Select->group_list,
Select->order_list,
- lex->win_frame ))
+ lex->win_frame))
MYSQL_YYABORT;
}
;
@@ -11565,7 +11662,7 @@ opt_window_ref:
/* empty */ {}
| ident
{
- thd->lex->win_ref= (LEX_STRING *) thd->memdup(&$1, sizeof(LEX_STRING));
+ thd->lex->win_ref= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
if (thd->lex->win_ref == NULL)
MYSQL_YYABORT;
}
@@ -11730,13 +11827,13 @@ order_clause:
yet.
*/
SELECT_LEX *first_sl= unit->first_select();
- if (!unit->is_union() &&
+ if (!unit->is_unit_op() &&
(first_sl->order_list.elements ||
first_sl->select_limit) &&
unit->add_fake_select_lex(thd))
MYSQL_YYABORT;
}
- if (sel->master_unit()->is_union() && !sel->braces)
+ if (sel->master_unit()->is_unit_op() && !sel->braces)
{
/*
At this point we don't know yet whether this is the last
@@ -11776,7 +11873,7 @@ limit_clause_init:
LIMIT
{
SELECT_LEX *sel= Select;
- if (sel->master_unit()->is_union() && !sel->braces)
+ if (sel->master_unit()->is_unit_op() && !sel->braces)
{
/* Move LIMIT that belongs to UNION to fake_select_lex */
Lex->current_select= sel->master_unit()->fake_select_lex;
@@ -11829,32 +11926,25 @@ limit_options:
;
limit_option:
- ident
+ ident_with_tok_start
{
- Item_splocal *splocal;
LEX *lex= thd->lex;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
- sp_variable *spv;
- sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_variable($1, false)))
- {
- splocal= new (thd->mem_root)
- Item_splocal(thd, $1, spv->offset, spv->sql_type(),
- lip->get_tok_start() - lex->sphead->m_tmp_query,
- lip->get_ptr() - lip->get_tok_start());
- if (splocal == NULL)
- MYSQL_YYABORT;
-#ifndef DBUG_OFF
- splocal->m_sp= lex->sphead;
-#endif
- lex->safe_to_cache_query=0;
- }
- else
- my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
- if (splocal->type() != Item::INT_ITEM)
- my_yyabort_error((ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)));
- splocal->limit_clause_param= TRUE;
- $$= splocal;
+ if (!($$= lex->create_item_limit(thd, &$1,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
+ | ident_with_tok_start '.' ident
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= & thd->m_parser_state->m_lip;
+ if (!($$= lex->create_item_limit(thd, &$1, &$3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_ptr() - $1.m_pos)))
+ MYSQL_YYABORT;
}
| param_marker
{
@@ -11900,23 +11990,26 @@ delete_limit_clause:
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
sel->explicit_limit= 1;
}
- | LIMIT ROWS_SYM EXAMINED_SYM { my_parse_error(thd, ER_SYNTAX_ERROR); MYSQL_YYABORT; }
- | LIMIT limit_option ROWS_SYM EXAMINED_SYM { my_parse_error(thd, ER_SYNTAX_ERROR); MYSQL_YYABORT; }
+ | LIMIT ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
+ | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
+ ;
+
+opt_plus:
+ /* empty */
+ | '+'
;
int_num:
- NUM { int error; $$= (int) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); }
| '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
- | '-' LONG_NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
- ;
ulong_num:
- NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
| HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
- | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | FLOAT_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulong_num:
@@ -11927,12 +12020,19 @@ real_ulong_num:
| dec_num_error { MYSQL_YYABORT; }
;
+longlong_num:
+ opt_plus NUM { int error; $$= (longlong) my_strtoll10($2.str, (char**) 0, &error); }
+ | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
+ | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
+ | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
+
+
ulonglong_num:
- NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulonglong_num:
@@ -11945,7 +12045,7 @@ real_ulonglong_num:
dec_num_error:
dec_num
- { my_parse_error(thd, ER_ONLY_INTEGERS_ALLOWED); }
+ { thd->parse_error(ER_ONLY_INTEGERS_ALLOWED); }
;
dec_num:
@@ -11958,6 +12058,12 @@ choice:
| DEFAULT { $$= HA_CHOICE_UNDEF; }
;
+bool:
+ ulong_num { $$= $1 != 0; }
+ | TRUE_SYM { $$= 1; }
+ | FALSE_SYM { $$= 0; }
+
+
procedure_clause:
PROCEDURE_SYM ident /* Procedure name */
{
@@ -11970,7 +12076,7 @@ procedure_clause:
lex->proc_list.next= &lex->proc_list.first;
Item_field *item= new (thd->mem_root)
Item_field(thd, &lex->current_select->context,
- NULL, NULL, $2.str);
+ NULL, NULL, &$2);
if (item == NULL)
MYSQL_YYABORT;
if (add_proc_to_list(thd, item))
@@ -12007,7 +12113,7 @@ procedure_item:
{
if (add_proc_to_list(thd, $2))
MYSQL_YYABORT;
- if (!$2->name)
+ if (!$2->name.str || $2->name.str == item_empty_name)
$2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
}
;
@@ -12050,19 +12156,24 @@ select_var_ident: select_outvar
select_outvar:
'@' ident_or_text
{
- $$ = Lex->result ? new (thd->mem_root) my_var_user($2) : NULL;
+ $$ = Lex->result ? new (thd->mem_root) my_var_user(&$2) : NULL;
}
| ident_or_text
{
sp_variable *t;
- if (!Lex->spcont || !(t= Lex->spcont->find_variable($1, false)))
+ if (!Lex->spcont || !(t= Lex->spcont->find_variable(&$1, false)))
my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
$$ = Lex->result ? (new (thd->mem_root)
- my_var_sp($1, t->offset, t->sql_type(),
+ my_var_sp(&$1, t->offset, t->type_handler(),
Lex->sphead)) :
NULL;
}
+ | ident '.' ident
+ {
+ if (!($$= Lex->create_outvar(thd, &$1, &$3)))
+ MYSQL_YYABORT;
+ }
;
into:
@@ -12160,31 +12271,29 @@ drop:
{
LEX *lex= thd->lex;
sp_name *spname;
- if ($4.str && check_db_name(&$4))
+ if ($4.str && check_db_name((LEX_STRING*) &$4))
my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $4.str));
if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
- spname= new (thd->mem_root) sp_name($4, $6, true);
+ spname= new (thd->mem_root) sp_name(&$4, &$6, true);
if (spname == NULL)
MYSQL_YYABORT;
- spname->init_qname(thd);
lex->spname= spname;
}
| DROP FUNCTION_SYM opt_if_exists ident
{
LEX *lex= thd->lex;
- LEX_STRING db= {0, 0};
+ LEX_CSTRING db= {0, 0};
sp_name *spname;
if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
- spname= new (thd->mem_root) sp_name(db, $4, false);
+ spname= new (thd->mem_root) sp_name(&db, &$4, false);
if (spname == NULL)
MYSQL_YYABORT;
- spname->init_qname(thd);
lex->spname= spname;
}
| DROP PROCEDURE_SYM opt_if_exists sp_name
@@ -12238,6 +12347,17 @@ drop:
Lex->set_command(SQLCOM_DROP_SERVER, $3);
Lex->server_options.reset($4);
}
+ | DROP opt_temporary SEQUENCE_SYM opt_if_exists
+
+ {
+ LEX *lex= Lex;
+ lex->set_command(SQLCOM_DROP_SEQUENCE, $2, $4);
+ lex->table_type= TABLE_TYPE_SEQUENCE;
+ YYPS->m_lock_type= TL_UNLOCK;
+ YYPS->m_mdl_type= MDL_EXCLUSIVE;
+ }
+ table_list
+ {}
;
table_list:
@@ -12456,6 +12576,16 @@ opt_equal:
| equal {}
;
+opt_with:
+ opt_equal {}
+ | WITH {}
+ ;
+
+opt_by:
+ opt_equal {}
+ | BY {}
+ ;
+
no_braces:
'('
{
@@ -12645,7 +12775,7 @@ table_wild_list:
table_wild_one:
ident opt_wild
{
- Table_ident *ti= new (thd->mem_root) Table_ident($1);
+ Table_ident *ti= new (thd->mem_root) Table_ident(&$1);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(thd,
@@ -12658,7 +12788,7 @@ table_wild_one:
}
| ident '.' ident opt_wild
{
- Table_ident *ti= new (thd->mem_root) Table_ident(thd, $1, $3, 0);
+ Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(thd,
@@ -12779,7 +12909,7 @@ show:
{
LEX *lex=Lex;
lex->wild=0;
- lex->ident=null_lex_str;
+ lex->ident= null_clex_str;
mysql_init_select(lex);
lex->current_select->parsing_place= SELECT_LIST;
lex->create_info.init();
@@ -12802,7 +12932,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.db= $3;
+ lex->select_lex.db= $3.str;
if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
MYSQL_YYABORT;
}
@@ -12810,7 +12940,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TRIGGERS;
- lex->select_lex.db= $3;
+ lex->select_lex.db= $3.str;
if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
MYSQL_YYABORT;
}
@@ -12818,7 +12948,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_EVENTS;
- lex->select_lex.db= $2;
+ lex->select_lex.db= $2.str;
if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
MYSQL_YYABORT;
}
@@ -12826,7 +12956,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
- lex->select_lex.db= $3;
+ lex->select_lex.db= $3.str;
if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
MYSQL_YYABORT;
}
@@ -12834,7 +12964,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
- lex->select_lex.db= $3;
+ lex->select_lex.db= $3.str;
if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
MYSQL_YYABORT;
}
@@ -12866,8 +12996,8 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_FIELDS;
- if ($5)
- $4->change_db($5);
+ if ($5.str)
+ $4->change_db(&$5);
if (prepare_schema_table(thd, lex, $4, SCH_COLUMNS))
MYSQL_YYABORT;
}
@@ -12894,8 +13024,8 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_KEYS;
- if ($4)
- $3->change_db($4);
+ if ($4.str)
+ $3->change_db(&$4);
if (prepare_schema_table(thd, lex, $3, SCH_STATISTICS))
MYSQL_YYABORT;
}
@@ -13002,7 +13132,15 @@ show_param:
lex->sql_command = SQLCOM_SHOW_CREATE;
if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
- lex->only_view= 1;
+ lex->table_type= TABLE_TYPE_VIEW;
+ }
+ | CREATE SEQUENCE_SYM table_ident
+ {
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_SHOW_CREATE;
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+ MYSQL_YYABORT;
+ lex->table_type= TABLE_TYPE_SEQUENCE;
}
| MASTER_SYM STATUS_SYM
{
@@ -13016,7 +13154,7 @@ show_param:
| SLAVE STATUS_SYM
{
LEX *lex= thd->lex;
- lex->mi.connection_name= null_lex_str;
+ lex->mi.connection_name= null_clex_str;
lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
lex->verbose= 0;
}
@@ -13101,12 +13239,12 @@ show_param:
ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str, &in_plugin);
if (!table || !table->old_format || !in_plugin)
{
- my_parse_error(thd, ER_SYNTAX_ERROR, $2);
+ thd->parse_error(ER_SYNTAX_ERROR, $2);
MYSQL_YYABORT;
}
if (lex->wild && table->idx_field1 < 0)
{
- my_parse_error(thd, ER_SYNTAX_ERROR, $3);
+ thd->parse_error(ER_SYNTAX_ERROR, $3);
MYSQL_YYABORT;
}
if (make_schema_select(thd, Lex->current_select, table))
@@ -13134,8 +13272,8 @@ opt_storage:
;
opt_db:
- /* empty */ { $$= 0; }
- | from_or_in ident { $$= $2.str; }
+ /* empty */ { $$= null_clex_str; }
+ | from_or_in ident { $$= $2; }
;
opt_full:
@@ -13294,8 +13432,10 @@ opt_flush_lock:
for (; tables; tables= tables->next_global)
{
tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
- tables->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
- tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
+ /* Don't try to flush views. */
+ tables->required_type= TABLE_TYPE_NORMAL;
+ /* Ignore temporary tables. */
+ tables->open_type= OT_BASE_ONLY;
}
}
;
@@ -13307,7 +13447,7 @@ flush_lock:
{
if (Lex->query_tables == NULL) // Table list can't be empty
{
- my_parse_error(thd, ER_NO_TABLES_USED);
+ thd->parse_error(ER_NO_TABLES_USED);
MYSQL_YYABORT;
}
Lex->type|= REFRESH_FOR_EXPORT;
@@ -13348,7 +13488,7 @@ flush_option:
| LOGS_SYM
{
Lex->type|= REFRESH_LOG;
- Lex->relay_log_connection_name= empty_lex_str;
+ Lex->relay_log_connection_name= empty_clex_str;
}
| STATUS_SYM
{ Lex->type|= REFRESH_STATUS; }
@@ -13372,7 +13512,7 @@ flush_option:
ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str);
if (!table || !table->reset_table)
{
- my_parse_error(thd, ER_SYNTAX_ERROR, $2);
+ thd->parse_error(ER_SYNTAX_ERROR, $2);
MYSQL_YYABORT;
}
Lex->view_list.push_back((LEX_STRING*)
@@ -13686,7 +13826,7 @@ field_or_var:
simple_ident_nospvar {$$= $1;}
| '@' ident_or_text
{
- $$= new (thd->mem_root) Item_user_var_as_out_param(thd, $2);
+ $$= new (thd->mem_root) Item_user_var_as_out_param(thd, &$2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13718,37 +13858,16 @@ load_data_set_elem:
text_literal:
TEXT_STRING
{
- LEX_STRING tmp;
- CHARSET_INFO *cs_con= thd->variables.collation_connection;
- CHARSET_INFO *cs_cli= thd->variables.character_set_client;
- uint repertoire= thd->lex->text_string_is_7bit &&
- my_charset_is_ascii_based(cs_cli) ?
- MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
- if (thd->charset_is_collation_connection ||
- (repertoire == MY_REPERTOIRE_ASCII &&
- my_charset_is_ascii_based(cs_con)))
- tmp= $1;
- else
- {
- if (thd->convert_string(&tmp, cs_con, $1.str, $1.length, cs_cli))
- MYSQL_YYABORT;
- }
- $$= new (thd->mem_root) Item_string(thd, tmp.str, tmp.length,
- cs_con,
- DERIVATION_COERCIBLE,
- repertoire);
- if ($$ == NULL)
+ if (!($$= thd->make_string_literal($1)))
MYSQL_YYABORT;
}
| NCHAR_STRING
{
- uint repertoire= Lex->text_string_is_7bit ?
- MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
$$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
national_charset_info,
DERIVATION_COERCIBLE,
- repertoire);
+ $1.repertoire());
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13831,17 +13950,10 @@ hex_or_bin_String:
param_marker:
PARAM_MARKER
{
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
- Item_param *item;
- if (! lex->parsing_options.allows_variable)
- my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
- const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
- : thd->query();
- item= new (thd->mem_root) Item_param(thd, lip->get_tok_start() -
- query_start);
- if (!($$= item) || lex->param_list.push_back(item, thd->mem_root))
- my_yyabort_error((ER_OUT_OF_RESOURCES, MYF(0)));
+ if (!($$= Lex->add_placeholder(thd, &param_clex_str,
+ YYLIP->get_tok_start(),
+ YYLIP->get_tok_start() + 1)))
+ MYSQL_YYABORT;
}
;
@@ -14032,7 +14144,7 @@ with_list_element:
query_name
opt_with_column_list
{
- $2= new List<LEX_STRING> (Lex->with_column_list);
+ $2= new List<LEX_CSTRING> (Lex->with_column_list);
if ($2 == NULL)
MYSQL_YYABORT;
Lex->with_column_list.empty();
@@ -14059,13 +14171,13 @@ opt_with_column_list:
with_column_list:
ident
{
- Lex->with_column_list.push_back((LEX_STRING*)
- thd->memdup(&$1, sizeof(LEX_STRING)));
+ Lex->with_column_list.push_back((LEX_CSTRING*)
+ thd->memdup(&$1, sizeof(LEX_CSTRING)));
}
| with_column_list ',' ident
{
- Lex->with_column_list.push_back((LEX_STRING*)
- thd->memdup(&$3, sizeof(LEX_STRING)));
+ Lex->with_column_list.push_back((LEX_CSTRING*)
+ thd->memdup(&$3, sizeof(LEX_CSTRING)));
}
;
@@ -14073,7 +14185,7 @@ with_column_list:
query_name:
ident
{
- $$= (LEX_STRING *) thd->memdup(&$1, sizeof(LEX_STRING));
+ $$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -14095,7 +14207,7 @@ table_wild:
{
SELECT_LEX *sel= Select;
$$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, $1.str, "*");
+ NullS, $1.str, &star_clex_str);
if ($$ == NULL)
MYSQL_YYABORT;
sel->with_wild++;
@@ -14107,7 +14219,7 @@ table_wild:
NullS : $1.str;
$$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
schema,
- $3.str,"*");
+ $3.str, &star_clex_str);
if ($$ == NULL)
MYSQL_YYABORT;
sel->with_wild++;
@@ -14121,66 +14233,28 @@ order_ident:
simple_ident:
ident
{
- LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
- sp_variable *spv;
- sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_variable($1, false)))
- {
- /* We're compiling a stored procedure and found a variable */
- if (! lex->parsing_options.allows_variable)
- my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
-
- Item_splocal *splocal;
- splocal= new (thd->mem_root)
- Item_splocal(thd, $1, spv->offset, spv->sql_type(),
- lip->get_tok_start_prev() - lex->sphead->m_tmp_query,
- lip->get_tok_end() - lip->get_tok_start_prev());
- if (splocal == NULL)
- MYSQL_YYABORT;
-#ifndef DBUG_OFF
- splocal->m_sp= lex->sphead;
-#endif
- $$= splocal;
- lex->safe_to_cache_query=0;
- }
- else
- {
- SELECT_LEX *sel=Select;
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, NullS, $1.str);
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- NullS, NullS, $1.str);
- }
- if ($$ == NULL)
- MYSQL_YYABORT;
- }
+ if (!($$= Lex->create_item_ident(thd, &$1,
+ lip->get_tok_start_prev(),
+ lip->get_tok_end())))
+ MYSQL_YYABORT;
+ }
+ | simple_ident_q2
+ | ident '.' ident
+ {
+ LEX *lex= thd->lex;
+ if (!($$= lex->create_item_ident(thd, &$1, &$3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ YYLIP->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
}
- | simple_ident_q { $$= $1; }
;
simple_ident_nospvar:
ident
{
- SELECT_LEX *sel=Select;
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, NullS, $1.str);
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- NullS, NullS, $1.str);
- }
- if ($$ == NULL)
+ if (!($$= Lex->create_item_ident_nosp(thd, &$1)))
MYSQL_YYABORT;
}
| simple_ident_q { $$= $1; }
@@ -14189,125 +14263,21 @@ simple_ident_nospvar:
simple_ident_q:
ident '.' ident
{
- LEX *lex= thd->lex;
-
- /*
- FIXME This will work ok in simple_ident_nospvar case because
- we can't meet simple_ident_nospvar in trigger now. But it
- should be changed in future.
- */
- if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
- (!my_strcasecmp(system_charset_info, $1.str, "NEW") ||
- !my_strcasecmp(system_charset_info, $1.str, "OLD")))
- {
- Item_trigger_field *trg_fld;
- bool new_row= ($1.str[0]=='N' || $1.str[0]=='n');
-
- if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
- !new_row)
- my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT"));
-
- if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
- new_row)
- my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"));
-
- DBUG_ASSERT(!new_row ||
- (lex->trg_chistics.event == TRG_EVENT_INSERT ||
- lex->trg_chistics.event == TRG_EVENT_UPDATE));
- const bool tmp_read_only=
- !(new_row && lex->trg_chistics.action_time == TRG_ACTION_BEFORE);
- trg_fld= new (thd->mem_root)
- Item_trigger_field(thd, Lex->current_context(),
- new_row ?
- Item_trigger_field::NEW_ROW:
- Item_trigger_field::OLD_ROW,
- $3.str,
- SELECT_ACL,
- tmp_read_only);
- if (trg_fld == NULL)
- MYSQL_YYABORT;
-
- /*
- Let us add this item to list of all Item_trigger_field objects
- in trigger.
- */
- lex->trg_table_fields.link_in_list(trg_fld,
- &trg_fld->next_trg_field);
-
- $$= trg_fld;
- }
- else
- {
- SELECT_LEX *sel= lex->current_select;
- if (sel->no_table_names_allowed)
- {
- my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- MYF(0), $1.str, thd->where);
- }
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, $1.str, $3.str);
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- NullS, $1.str, $3.str);
- }
- if ($$ == NULL)
- MYSQL_YYABORT;
- }
+ if (!($$= Lex->create_item_ident_nospvar(thd, &$1, &$3)))
+ MYSQL_YYABORT;
}
- | '.' ident '.' ident
- {
- LEX *lex= thd->lex;
- SELECT_LEX *sel= lex->current_select;
- if (sel->no_table_names_allowed)
- {
- my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- MYF(0), $2.str, thd->where);
- }
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, $2.str, $4.str);
+ | simple_ident_q2
+ ;
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- NullS, $2.str, $4.str);
- }
- if ($$ == NULL)
+simple_ident_q2:
+ '.' ident '.' ident
+ {
+ if (!($$= Lex->create_item_ident(thd, &null_clex_str, &$2, &$4)))
MYSQL_YYABORT;
}
| ident '.' ident '.' ident
{
- LEX *lex= thd->lex;
- SELECT_LEX *sel= lex->current_select;
- const char* schema= (thd->client_capabilities & CLIENT_NO_SCHEMA ?
- NullS : $1.str);
- if (sel->no_table_names_allowed)
- {
- my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- MYF(0), $3.str, thd->where);
- }
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- schema,
- $3.str, $5.str);
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- schema,
- $3.str, $5.str);
- }
- if ($$ == NULL)
+ if (!($$= Lex->create_item_ident(thd, &$1, &$3, &$5)))
MYSQL_YYABORT;
}
;
@@ -14337,20 +14307,20 @@ field_ident:
table_ident:
ident
{
- $$= new (thd->mem_root) Table_ident($1);
+ $$= new (thd->mem_root) Table_ident(&$1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ident '.' ident
{
- $$= new (thd->mem_root) Table_ident(thd, $1, $3, 0);
+ $$= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '.' ident
{
/* For Delphi */
- $$= new (thd->mem_root) Table_ident($2);
+ $$= new (thd->mem_root) Table_ident(&$2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -14359,13 +14329,13 @@ table_ident:
table_ident_opt_wild:
ident opt_wild
{
- $$= new (thd->mem_root) Table_ident($1);
+ $$= new (thd->mem_root) Table_ident(&$1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ident '.' ident opt_wild
{
- $$= new (thd->mem_root) Table_ident(thd, $1, $3, 0);
+ $$= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -14374,8 +14344,8 @@ table_ident_opt_wild:
table_ident_nodb:
ident
{
- LEX_STRING db={(char*) any_db,3};
- $$= new (thd->mem_root) Table_ident(thd, db, $1, 0);
+ LEX_CSTRING db={(char*) any_db,3};
+ $$= new (thd->mem_root) Table_ident(thd, &db, &$1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -14400,9 +14370,12 @@ IDENT_sys:
}
else
{
- if (thd->convert_with_error(system_charset_info, &$$,
+ LEX_STRING to;
+ if (thd->convert_with_error(system_charset_info, &to,
thd->charset(), $1.str, $1.length))
MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
}
}
;
@@ -14414,9 +14387,12 @@ TEXT_STRING_sys:
$$= $1;
else
{
- if (thd->convert_string(&$$, system_charset_info,
+ LEX_STRING to;
+ if (thd->convert_string(&to, system_charset_info,
$1.str, $1.length, thd->charset()))
MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
}
}
;
@@ -14428,10 +14404,13 @@ TEXT_STRING_literal:
$$= $1;
else
{
- if (thd->convert_string(&$$, thd->variables.collation_connection,
+ LEX_STRING to;
+ if (thd->convert_string(&to, thd->variables.collation_connection,
$1.str, $1.length, thd->charset()))
MYSQL_YYABORT;
- }
+ $$.str= to.str;
+ $$.length= to.length;
+ }
}
;
@@ -14442,22 +14421,45 @@ TEXT_STRING_filesystem:
$$= $1;
else
{
- if (thd->convert_string(&$$,
+ LEX_STRING to;
+ if (thd->convert_string(&to,
thd->variables.character_set_filesystem,
$1.str, $1.length, thd->charset()))
MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
}
}
;
ident:
- IDENT_sys { $$=$1; }
+ IDENT_sys
+ {
+ (LEX_CSTRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
| keyword
{
$$.str= thd->strmake($1.str, $1.length);
if ($$.str == NULL)
MYSQL_YYABORT;
$$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
+ ;
+
+ident_with_tok_start:
+ IDENT_sys
+ {
+ (LEX_CSTRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
+ }
+ | keyword
+ {
+ if (!($$.str= thd->strmake($1.str, $1.length)))
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
}
;
@@ -14481,10 +14483,10 @@ ident_or_text:
user_maybe_role:
ident_or_text
{
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
$$->user = $1;
- $$->host= null_lex_str; // User or Role, see get_current_user()
+ $$->host= null_clex_str; // User or Role, see get_current_user()
$$->reset_auth();
if (check_string_char_length(&$$->user, ER_USERNAME,
@@ -14494,7 +14496,7 @@ user_maybe_role:
}
| ident_or_text '@' ident_or_text
{
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
$$->user = $1; $$->host=$3;
$$->reset_auth();
@@ -14511,7 +14513,7 @@ user_maybe_role:
It's OK to use in-place lowercase as long as
the character set is utf8.
*/
- my_casedn_str(system_charset_info, $$->host.str);
+ my_casedn_str(system_charset_info, (char*) $$->host.str);
}
else
{
@@ -14527,8 +14529,8 @@ user_maybe_role:
if (!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
$$->user= current_user;
- $$->plugin= empty_lex_str;
- $$->auth= empty_lex_str;
+ $$->plugin= empty_clex_str;
+ $$->auth= empty_clex_str;
}
;
@@ -14545,27 +14547,23 @@ user: user_maybe_role
/* Keyword that we allow for identifiers (except SP labels) */
keyword:
keyword_sp {}
+ | keyword_sp_verb_clause{}
| ASCII_SYM {}
| BACKUP_SYM {}
- | BEGIN_SYM {}
| BINLOG_SYM {}
| BYTE_SYM {}
| CACHE_SYM {}
| CHARSET {}
| CHECKSUM_SYM {}
| CHECKPOINT_SYM {}
- | CLOSE_SYM {}
| COLUMN_ADD_SYM {}
| COLUMN_CHECK_SYM {}
| COLUMN_CREATE_SYM {}
| COLUMN_DELETE_SYM {}
| COLUMN_GET_SYM {}
| COMMENT_SYM {}
- | COMMIT_SYM {}
| CONTAINS_SYM {}
| DEALLOCATE_SYM {}
- | DO_SYM {}
- | END {}
| EXAMINED_SYM {}
| EXCLUDE_SYM {}
| EXECUTE_SYM {}
@@ -14574,13 +14572,11 @@ keyword:
| FOLLOWING_SYM {}
| FORMAT_SYM {}
| GET_SYM {}
- | HANDLER_SYM {}
| HELP_SYM {}
| HOST_SYM {}
| INSTALL_SYM {}
| LANGUAGE_SYM {}
| NO_SYM {}
- | OPEN_SYM {}
| OPTION {}
| OPTIONS_SYM {}
| OTHERS_SYM {}
@@ -14591,14 +14587,10 @@ keyword:
| PRECEDING_SYM {}
| PREPARE_SYM {}
| REMOVE_SYM {}
- | REPAIR {}
| RESET_SYM {}
| RESTORE_SYM {}
- | ROLLBACK_SYM {}
- | SAVEPOINT_SYM {}
| SECURITY_SYM {}
| SERVER_SYM {}
- | SHUTDOWN {}
| SIGNED_SYM {}
| SOCKET_SYM {}
| SLAVE {}
@@ -14608,7 +14600,6 @@ keyword:
| STOP_SYM {}
| STORED_SYM {}
| TIES_SYM {}
- | TRUNCATE_SYM {}
| UNICODE_SYM {}
| UNINSTALL_SYM {}
| UNBOUNDED_SYM {}
@@ -14624,6 +14615,73 @@ keyword:
* conflicts.
*/
keyword_sp:
+ keyword_sp_data_type
+ | keyword_sp_not_data_type
+ ;
+
+
+/*
+ Keywords that start a statement.
+ Generally allowed as identifiers (e.g. table, column names)
+ - not allowed as SP label names
+ - not allowed as variable names in Oracle-style assignments:
+ xxx:=10
+*/
+keyword_sp_verb_clause:
+ BEGIN_SYM { /* Compound. Reserved in Oracle */ }
+ | CLOSE_SYM { /* Verb clause. Reserved in Oracle */ }
+ | COMMIT_SYM { /* Verb clause. Reserved in Oracle */ }
+ | DO_SYM { /* Verb clause */ }
+ | END { /* Compound. Reserved in Oracle */ }
+ | HANDLER_SYM { /* Verb clause */ }
+ | OPEN_SYM { /* Verb clause. Reserved in Oracle */ }
+ | REPAIR { /* Verb clause */ }
+ | ROLLBACK_SYM { /* Verb clause. Reserved in Oracle */ }
+ | SAVEPOINT_SYM { /* Verb clause. Reserved in Oracle */ }
+ | SHUTDOWN { /* Verb clause */ }
+ | TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
+ ;
+
+
+/*
+ These keywords are generally allowed as identifiers,
+ but not allowed as non-delimited SP variable names in sql_mode=ORACLE.
+*/
+keyword_sp_data_type:
+ BIT_SYM {}
+ | BOOLEAN_SYM {} /* PLSQL-R */
+ | BOOL_SYM {}
+ | CLOB {}
+ | DATE_SYM {} /* Oracle-R, PLSQL-R */
+ | DATETIME {}
+ | ENUM {}
+ | FIXED_SYM {}
+ | GEOMETRYCOLLECTION {}
+ | GEOMETRY_SYM {}
+ | JSON_SYM {}
+ | LINESTRING {}
+ | MEDIUM_SYM {}
+ | MULTILINESTRING {}
+ | MULTIPOINT {}
+ | MULTIPOLYGON {}
+ | NATIONAL_SYM {}
+ | NCHAR_SYM {}
+ | NUMBER_SYM {} /* Oracle-R, PLSQL-R */
+ | NVARCHAR_SYM {}
+ | POINT_SYM {}
+ | POLYGON {}
+ | RAW {} /* Oracle-R */
+ | ROW_SYM {}
+ | SERIAL_SYM {}
+ | TEXT_SYM {}
+ | TIMESTAMP {}
+ | TIME_SYM {} /* Oracle-R */
+ | VARCHAR2 {} /* Oracle-R, PLSQL-R */
+ | YEAR_SYM {}
+ ;
+
+
+keyword_sp_not_data_type:
ACTION {}
| ADDDATE_SYM {}
| ADMIN_SYM {}
@@ -14641,10 +14699,7 @@ keyword_sp:
| AUTO_SYM {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
- | BIT_SYM {}
| BLOCK_SYM {}
- | BOOL_SYM {}
- | BOOLEAN_SYM {}
| BTREE_SYM {}
| CASCADED {}
| CATALOG_NAME_SYM {}
@@ -14679,11 +14734,11 @@ keyword_sp:
*/
| CURRENT_SYM {}
| CURSOR_NAME_SYM {}
+ | CYCLE_SYM {}
| DATA_SYM {}
| DATAFILE_SYM {}
- | DATETIME {}
- | DATE_SYM {}
| DAY_SYM {}
+ | DECODE_SYM {}
| DEFINER_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
@@ -14695,8 +14750,8 @@ keyword_sp:
| DUMPFILE {}
| DUPLICATE_SYM {}
| DYNAMIC_SYM {}
+ | ELSIF_SYM {}
| ENDS_SYM {}
- | ENUM {}
| ENGINE_SYM {}
| ENGINES_SYM {}
| ERROR_SYM {}
@@ -14705,6 +14760,7 @@ keyword_sp:
| EVENT_SYM {}
| EVENTS_SYM {}
| EVERY_SYM {}
+ | EXCEPTION_SYM {}
| EXCHANGE_SYM {}
| EXPANSION_SYM {}
| EXPORT_SYM {}
@@ -14717,14 +14773,12 @@ keyword_sp:
| FULL {}
| FILE_SYM {}
| FIRST_SYM {}
- | FIXED_SYM {}
| GENERAL {}
| GENERATED_SYM {}
- | GEOMETRY_SYM {}
- | GEOMETRYCOLLECTION {}
| GET_FORMAT {}
| GRANTS {}
| GLOBAL_SYM {}
+ | GOTO_SYM {}
| HASH_SYM {}
| HARD_SYM {}
| HOSTS_SYM {}
@@ -14732,6 +14786,7 @@ keyword_sp:
| ID_SYM {}
| IDENTIFIED_SYM {}
| IGNORE_SERVER_IDS_SYM {}
+ | INCREMENT_SYM {}
| IMMEDIATE_SYM {} /* SQL-2003-R */
| INVOKER_SYM {}
| IMPORT {}
@@ -14740,16 +14795,16 @@ keyword_sp:
| IO_SYM {}
| IPC_SYM {}
| ISOLATION {}
+ | ISOPEN_SYM {}
| ISSUER_SYM {}
- | JSON_SYM {}
| INSERT_METHOD {}
| KEY_BLOCK_SIZE {}
| LAST_VALUE {}
| LAST_SYM {}
+ | LASTVAL_SYM {}
| LEAVES {}
| LESS_SYM {}
| LEVEL_SYM {}
- | LINESTRING {}
| LIST_SYM {}
| LOCAL_SYM {}
| LOCKS_SYM {}
@@ -14783,34 +14838,34 @@ keyword_sp:
| MAX_STATEMENT_TIME_SYM {}
| MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {}
- | MEDIUM_SYM {}
| MEMORY_SYM {}
| MERGE_SYM {}
| MESSAGE_TEXT_SYM {}
| MICROSECOND_SYM {}
| MIGRATE_SYM {}
| MINUTE_SYM {}
+ | MINVALUE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
| MODE_SYM {}
| MONTH_SYM {}
- | MULTILINESTRING {}
- | MULTIPOINT {}
- | MULTIPOLYGON {}
| MUTEX_SYM {}
| MYSQL_SYM {}
| MYSQL_ERRNO_SYM {}
| NAME_SYM {}
| NAMES_SYM {}
- | NATIONAL_SYM {}
- | NCHAR_SYM {}
| NEXT_SYM {}
+ | NEXTVAL_SYM {}
| NEW_SYM {}
+ | NOCACHE_SYM {}
+ | NOCYCLE_SYM {}
+ | NOMINVALUE_SYM {}
+ | NOMAXVALUE_SYM {}
| NO_WAIT_SYM {}
| NODEGROUP_SYM {}
| NONE_SYM {}
- | NUMBER_SYM {}
- | NVARCHAR_SYM {}
+ | NOTFOUND_SYM {}
+ | OF_SYM {} /* SQL-1999-R, Oracle-R */
| OFFSET_SYM {}
| OLD_PASSWORD_SYM {}
| ONE_SYM {}
@@ -14826,10 +14881,9 @@ keyword_sp:
| PHASE_SYM {}
| PLUGIN_SYM {}
| PLUGINS_SYM {}
- | POINT_SYM {}
- | POLYGON {}
| PRESERVE_SYM {}
| PREV_SYM {}
+ | PREVIOUS_SYM {}
| PRIVILEGES {}
| PROCESS {}
| PROCESSLIST_SYM {}
@@ -14839,6 +14893,7 @@ keyword_sp:
| QUARTER_SYM {}
| QUERY_SYM {}
| QUICK {}
+ | RAISE_SYM {}
| READ_ONLY_SYM {}
| REBUILD_SYM {}
| RECOVER_SYM {}
@@ -14855,23 +14910,27 @@ keyword_sp:
| REPEATABLE_SYM {}
| REPLICATION {}
| RESOURCES {}
+ | RESTART_SYM {}
| RESUME_SYM {}
| RETURNED_SQLSTATE_SYM {}
| RETURNS_SYM {}
+ | REUSE_SYM {} /* Oracle-R */
| REVERSE_SYM {}
| ROLE_SYM {}
| ROLLUP_SYM {}
| ROUTINE_SYM {}
+ | ROWCOUNT_SYM {}
+ | ROWTYPE_SYM {}
| ROW_COUNT_SYM {}
| ROW_FORMAT_SYM {}
- | ROW_SYM {}
| RTREE_SYM {}
| SCHEDULE_SYM {}
| SCHEMA_NAME_SYM {}
| SECOND_SYM {}
- | SERIAL_SYM {}
+ | SEQUENCE_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
+ | SETVAL_SYM {}
| SIMPLE_SYM {}
| SHARE_SYM {}
| SLAVE_POS_SYM {}
@@ -14904,15 +14963,12 @@ keyword_sp:
| TABLESPACE {}
| TEMPORARY {}
| TEMPTABLE_SYM {}
- | TEXT_SYM {}
| THAN_SYM {}
| TRANSACTION_SYM {}
| TRANSACTIONAL_SYM {}
| TRIGGERS_SYM {}
- | TIMESTAMP {}
| TIMESTAMP_ADD {}
| TIMESTAMP_DIFF {}
- | TIME_SYM {}
| TYPES_SYM {}
| TYPE_SYM {}
| UDF_RETURNS_SYM {}
@@ -14936,8 +14992,7 @@ keyword_sp:
| WORK_SYM {}
| X509_SYM {}
| XML_SYM {}
- | YEAR_SYM {}
- | VIA_SYM {}
+ | VIA_SYM {}
;
/*
@@ -14951,22 +15006,15 @@ set:
SET
{
LEX *lex=Lex;
- lex->sql_command= SQLCOM_SET_OPTION;
- mysql_init_select(lex);
- lex->option_type=OPT_SESSION;
+ lex->set_stmt_init();
lex->var_list.empty();
- lex->autocommit= 0;
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
{}
| SET STATEMENT_SYM
{
- LEX *lex= Lex;
- mysql_init_select(lex);
- lex->option_type= OPT_SESSION;
- lex->sql_command= SQLCOM_SET_OPTION;
- lex->autocommit= 0;
+ Lex->set_stmt_init();
}
set_stmt_option_value_following_option_type_list
{
@@ -15096,7 +15144,7 @@ option_value_following_option_type:
if ($1.var && $1.var != trg_new_row_fake_var)
{
/* It is a system variable. */
- if (set_system_variable(thd, &$1, lex->option_type, $3))
+ if (lex->set_system_variable(&$1, lex->option_type, $3))
MYSQL_YYABORT;
}
else
@@ -15105,7 +15153,7 @@ option_value_following_option_type:
Not in trigger assigning value to new row,
and option_type preceding local variable is illegal.
*/
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
}
@@ -15113,36 +15161,30 @@ option_value_following_option_type:
/* Option values without preceding option_type. */
option_value_no_option_type:
- internal_variable_name equal set_expr_or_default
+ ident equal set_expr_or_default
{
- LEX *lex= Lex;
-
- if ($1.var == trg_new_row_fake_var)
- {
- /* We are in trigger and assigning value to field of new row */
- if (set_trigger_new_row(thd, &$1.base_name, $3))
- MYSQL_YYABORT;
- }
- else if ($1.var)
- {
- /* It is a system variable. */
- if (set_system_variable(thd, &$1, lex->option_type, $3))
- MYSQL_YYABORT;
- }
- else
- {
- sp_pcontext *spc= lex->spcont;
- sp_variable *spv= spc->find_variable($1.base_name, false);
-
- /* It is a local variable. */
- if (set_local_variable(thd, spv, $3))
- MYSQL_YYABORT;
- }
+ struct sys_var_with_base var;
+ if (Lex->init_internal_variable(&var, &$1) ||
+ Lex->set_variable(&var, $3))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident equal set_expr_or_default
+ {
+ DBUG_ASSERT(Lex->var_list.is_empty());
+ if (Lex->set_variable(&$1, &$3, $5))
+ MYSQL_YYABORT;
+ }
+ | DEFAULT '.' ident equal set_expr_or_default
+ {
+ struct sys_var_with_base var;
+ if (Lex->init_default_internal_variable(&var, $3) ||
+ Lex->set_variable(&var, $5))
+ MYSQL_YYABORT;
}
| '@' ident_or_text equal expr
{
Item_func_set_user_var *item;
- item= new (thd->mem_root) Item_func_set_user_var(thd, $2, $4);
+ item= new (thd->mem_root) Item_func_set_user_var(thd, &$2, $4);
if (item == NULL)
MYSQL_YYABORT;
set_var_user *var= new (thd->mem_root) set_var_user(item);
@@ -15159,7 +15201,7 @@ option_value_no_option_type:
if (find_sys_var_null_base(thd, &tmp))
MYSQL_YYABORT;
}
- if (set_system_variable(thd, &tmp, $3, $6))
+ if (Lex->set_system_variable(&tmp, $3, $6))
MYSQL_YYABORT;
}
| charset old_or_new_charset_name_or_default
@@ -15180,15 +15222,11 @@ option_value_no_option_type:
{
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- LEX_STRING names;
-
- names.str= (char *)"names";
- names.length= 5;
- if (spc && spc->find_variable(names, false))
+ LEX_CSTRING names= { STRING_WITH_LEN("names") };
+ if (spc && spc->find_variable(&names, false))
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
else
- my_parse_error(thd, ER_SYNTAX_ERROR);
-
+ thd->parse_error();
MYSQL_YYABORT;
}
| NAMES_SYM charset_name_or_default opt_collate
@@ -15265,77 +15303,18 @@ option_value_no_option_type:
internal_variable_name:
ident
{
- sp_pcontext *spc= thd->lex->spcont;
- sp_variable *spv;
-
- /* Best effort lookup for system variable. */
- if (!spc || !(spv = spc->find_variable($1, false)))
- {
- struct sys_var_with_base tmp= {NULL, $1};
-
- /* Not an SP local variable */
- if (find_sys_var_null_base(thd, &tmp))
- MYSQL_YYABORT;
-
- $$= tmp;
- }
- else
- {
- /*
- Possibly an SP local variable (or a shadowed sysvar).
- Will depend on the context of the SET statement.
- */
- $$.var= NULL;
- $$.base_name= $1;
- }
+ if (Lex->init_internal_variable(&$$, &$1))
+ MYSQL_YYABORT;
}
| ident '.' ident
{
- LEX *lex= Lex;
- if (check_reserved_words(&$1))
- {
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ if (Lex->init_internal_variable(&$$, &$1, &$3))
MYSQL_YYABORT;
- }
- if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
- (!my_strcasecmp(system_charset_info, $1.str, "NEW") ||
- !my_strcasecmp(system_charset_info, $1.str, "OLD")))
- {
- if ($1.str[0]=='O' || $1.str[0]=='o')
- my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""));
- if (lex->trg_chistics.event == TRG_EVENT_DELETE)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
- "NEW", "on DELETE");
- MYSQL_YYABORT;
- }
- if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
- my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "));
- /* This special combination will denote field of NEW row */
- $$.var= trg_new_row_fake_var;
- $$.base_name= $3;
- }
- else
- {
- sys_var *tmp=find_sys_var(thd, $3.str, $3.length);
- if (!tmp)
- MYSQL_YYABORT;
- if (!tmp->is_struct())
- my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
- $$.var= tmp;
- $$.base_name= $1;
- }
}
| DEFAULT '.' ident
{
- sys_var *tmp=find_sys_var(thd, $3.str, $3.length);
- if (!tmp)
+ if (Lex->init_default_internal_variable(&$$, $3))
MYSQL_YYABORT;
- if (!tmp->is_struct())
- my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
- $$.var= tmp;
- $$.base_name.str= (char*) "default";
- $$.base_name.length= 7;
}
;
@@ -15356,7 +15335,7 @@ transaction_access_mode:
set_var *var= (new (thd->mem_root)
set_var(thd, lex->option_type,
find_sys_var(thd, "tx_read_only"),
- &null_lex_str,
+ &null_clex_str,
item));
if (var == NULL)
MYSQL_YYABORT;
@@ -15374,7 +15353,7 @@ isolation_level:
set_var *var= (new (thd->mem_root)
set_var(thd, lex->option_type,
find_sys_var(thd, "tx_isolation"),
- &null_lex_str,
+ &null_clex_str,
item));
if (var == NULL)
MYSQL_YYABORT;
@@ -15399,15 +15378,15 @@ opt_for_user:
{
LEX *lex= thd->lex;
sp_pcontext *spc= lex->spcont;
- LEX_STRING pw= { C_STRING_WITH_LEN("password") };
+ LEX_CSTRING pw= { STRING_WITH_LEN("password") };
- if (spc && spc->find_variable(pw, false))
+ if (spc && spc->find_variable(&pw, false))
my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
if (!(lex->definer= (LEX_USER*) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
lex->definer->user= current_user;
- lex->definer->plugin= empty_lex_str;
- lex->definer->auth= empty_lex_str;
+ lex->definer->plugin= empty_clex_str;
+ lex->definer->auth= empty_clex_str;
}
| FOR_SYM user equal { Lex->definer= $2; }
;
@@ -15566,7 +15545,7 @@ handler:
;
handler_read_or_scan:
- handler_scan_function { Lex->ident= null_lex_str; }
+ handler_scan_function { Lex->ident= null_clex_str; }
| ident handler_rkey_function { Lex->ident= $1; }
;
@@ -15619,7 +15598,7 @@ revoke_command:
LEX *lex= Lex;
if (lex->columns.elements)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
lex->sql_command= SQLCOM_REVOKE;
@@ -15630,7 +15609,7 @@ revoke_command:
LEX *lex= Lex;
if (lex->columns.elements)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
lex->sql_command= SQLCOM_REVOKE;
@@ -15681,7 +15660,7 @@ grant_command:
LEX *lex= Lex;
if (lex->columns.elements)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
lex->sql_command= SQLCOM_GRANT;
@@ -15693,7 +15672,7 @@ grant_command:
LEX *lex= Lex;
if (lex->columns.elements)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
lex->sql_command= SQLCOM_GRANT;
@@ -15754,13 +15733,13 @@ grant_role:
CHARSET_INFO *cs= system_charset_info;
/* trim end spaces (as they'll be lost in mysql.user anyway) */
$1.length= cs->cset->lengthsp(cs, $1.str, $1.length);
- $1.str[$1.length] = '\0';
+ ((char*) $1.str)[$1.length] = '\0';
if ($1.length == 0)
my_yyabort_error((ER_INVALID_ROLE, MYF(0), ""));
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
- $$->user = $1;
- $$->host= empty_lex_str;
+ $$->user= $1;
+ $$->host= empty_clex_str;
$$->reset_auth();
if (check_string_char_length(&$$->user, ER_USERNAME,
@@ -15970,7 +15949,7 @@ grant_user:
{
$$= $1;
$1->plugin= $4;
- $1->auth= empty_lex_str;
+ $1->auth= empty_clex_str;
}
| user IDENTIFIED_SYM via_or_with ident_or_text using_or_as TEXT_STRING_sys
{
@@ -16152,11 +16131,6 @@ opt_release:
| NO_SYM RELEASE_SYM { $$= TVL_NO; }
;
-opt_savepoint:
- /* empty */ {}
- | SAVEPOINT_SYM {}
- ;
-
commit:
COMMIT_SYM opt_work opt_chain opt_release
{
@@ -16179,13 +16153,18 @@ rollback:
lex->tx_chain= $3;
lex->tx_release= $4;
}
- | ROLLBACK_SYM opt_work
- TO_SYM opt_savepoint ident
+ | ROLLBACK_SYM opt_work TO_SYM SAVEPOINT_SYM ident
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
lex->ident= $5;
}
+ | ROLLBACK_SYM opt_work TO_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
+ lex->ident= $4;
+ }
;
savepoint:
@@ -16210,6 +16189,14 @@ release:
UNIONS : glue selects together
*/
+unit_type_decl:
+ UNION_SYM
+ { $$= UNION_TYPE; }
+ | INTERSECT_SYM
+ { $$= INTERSECT_TYPE; }
+ | EXCEPT_SYM
+ { $$= EXCEPT_TYPE; }
+
union_clause:
/* empty */ {}
@@ -16217,9 +16204,9 @@ union_clause:
;
union_list:
- UNION_SYM union_option
+ unit_type_decl union_option
{
- if (add_select_to_union_list(Lex, (bool)$2, TRUE))
+ if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
MYSQL_YYABORT;
}
union_list_part2
@@ -16233,9 +16220,9 @@ union_list:
;
union_list_view:
- UNION_SYM union_option
+ unit_type_decl union_option
{
- if (add_select_to_union_list(Lex, (bool)$2, TRUE))
+ if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
MYSQL_YYABORT;
}
query_expression_body_view
@@ -16274,9 +16261,9 @@ order_or_limit:
Start a UNION, for non-top level query expressions.
*/
union_head_non_top:
- UNION_SYM union_option
+ unit_type_decl union_option
{
- if (add_select_to_union_list(Lex, (bool)$2, FALSE))
+ if (Lex->add_select_to_union_list((bool)$2, $1, FALSE))
MYSQL_YYABORT;
}
;
@@ -16334,7 +16321,7 @@ subselect_start:
if (!lex->expr_allows_subselect ||
lex->sql_command == (int)SQLCOM_PURGE)
{
- my_parse_error(thd, ER_SYNTAX_ERROR);
+ thd->parse_error();
MYSQL_YYABORT;
}
/*
@@ -16344,7 +16331,7 @@ subselect_start:
(SELECT .. ) UNION ... becomes
SELECT * FROM ((SELECT ...) UNION ...)
*/
- if (mysql_new_select(Lex, 1))
+ if (mysql_new_select(Lex, 1, NULL))
MYSQL_YYABORT;
}
;
@@ -16353,6 +16340,7 @@ subselect_end:
{
LEX *lex=Lex;
+ lex->check_automatic_up(UNSPECIFIED_TYPE);
lex->pop_context();
SELECT_LEX *child= lex->current_select;
lex->current_select = lex->current_select->return_after_parsing();
@@ -16414,38 +16402,6 @@ query_expression_option:
/**************************************************************************
- CREATE VIEW | TRIGGER | PROCEDURE statements.
-
-**************************************************************************/
-
-view_or_trigger_or_sp_or_event:
- definer definer_tail
- {}
- | no_definer no_definer_tail
- {}
- | view_algorithm definer_opt view_tail
- {}
- ;
-
-definer_tail:
- view_tail
- | trigger_tail
- | sp_tail
- | sf_tail
- | event_tail
- ;
-
-no_definer_tail:
- view_tail
- | trigger_tail
- | sp_tail
- | sf_tail
- | udf_tail
- | event_tail
- ;
-
-/**************************************************************************
-
DEFINER clause support.
**************************************************************************/
@@ -16486,39 +16442,19 @@ definer:
**************************************************************************/
view_algorithm:
- ALGORITHM_SYM '=' UNDEFINED_SYM
- { Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; }
- | ALGORITHM_SYM '=' MERGE_SYM
- { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
- | ALGORITHM_SYM '=' TEMPTABLE_SYM
- { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
+ ALGORITHM_SYM '=' UNDEFINED_SYM { $$= DTYPE_ALGORITHM_UNDEFINED; }
+ | ALGORITHM_SYM '=' MERGE_SYM { $$= VIEW_ALGORITHM_MERGE; }
+ | ALGORITHM_SYM '=' TEMPTABLE_SYM { $$= VIEW_ALGORITHM_TMPTABLE; }
;
-view_suid:
- /* empty */
- { Lex->create_view_suid= VIEW_SUID_DEFAULT; }
- | SQL_SYM SECURITY_SYM DEFINER_SYM
- { Lex->create_view_suid= VIEW_SUID_DEFINER; }
- | SQL_SYM SECURITY_SYM INVOKER_SYM
- { Lex->create_view_suid= VIEW_SUID_INVOKER; }
+opt_view_suid:
+ /* empty */ { $$= VIEW_SUID_DEFAULT; }
+ | view_suid { $$= $1; }
;
-view_tail:
- view_suid VIEW_SYM opt_if_not_exists table_ident
- {
- LEX *lex= thd->lex;
- if (lex->add_create_options_with_check($3))
- MYSQL_YYABORT;
- lex->sql_command= SQLCOM_CREATE_VIEW;
- /* first table in list is target VIEW name */
- if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
- TL_OPTION_UPDATING,
- TL_IGNORE,
- MDL_EXCLUSIVE))
- MYSQL_YYABORT;
- lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
- }
- view_list_opt AS view_select
+view_suid:
+ SQL_SYM SECURITY_SYM DEFINER_SYM { $$= VIEW_SUID_DEFINER; }
+ | SQL_SYM SECURITY_SYM INVOKER_SYM { $$= VIEW_SUID_INVOKER; }
;
view_list_opt:
@@ -16546,18 +16482,20 @@ view_select:
{
LEX *lex= Lex;
lex->parsing_options.allows_variable= FALSE;
- lex->create_view_select.str= (char *) YYLIP->get_cpp_ptr();
+ lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
}
opt_with_clause query_expression_body_view view_check_option
{
LEX *lex= Lex;
- uint len= YYLIP->get_cpp_ptr() - lex->create_view_select.str;
+ uint len= YYLIP->get_cpp_ptr() - lex->create_view->select.str;
uint not_used;
- void *create_view_select= thd->memdup(lex->create_view_select.str, len);
- lex->create_view_select.length= len;
- lex->create_view_select.str= (char *) create_view_select;
- trim_whitespace(thd->charset(), &lex->create_view_select,
+ void *create_view_select= thd->memdup(lex->create_view->select.str, len);
+ lex->create_view->select.length= len;
+ lex->create_view->select.str= (char *) create_view_select;
+ trim_whitespace(thd->charset(),
+ &lex->create_view->select,
&not_used);
+ lex->create_view->check= $4;
lex->parsing_options.allows_variable= TRUE;
lex->current_select->set_with_clause($2);
}
@@ -16575,14 +16513,10 @@ query_expression_body_view:
;
view_check_option:
- /* empty */
- { Lex->create_view_check= VIEW_CHECK_NONE; }
- | WITH CHECK_SYM OPTION
- { Lex->create_view_check= VIEW_CHECK_CASCADED; }
- | WITH CASCADED CHECK_SYM OPTION
- { Lex->create_view_check= VIEW_CHECK_CASCADED; }
- | WITH LOCAL_SYM CHECK_SYM OPTION
- { Lex->create_view_check= VIEW_CHECK_LOCAL; }
+ /* empty */ { $$= VIEW_CHECK_NONE; }
+ | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
+ | WITH CASCADED CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
+ | WITH LOCAL_SYM CHECK_SYM OPTION { $$= VIEW_CHECK_LOCAL; }
;
/**************************************************************************
@@ -16614,25 +16548,24 @@ trigger_follows_precedes_clause:
;
trigger_tail:
- TRIGGER_SYM
remember_name
opt_if_not_exists
{
- if (Lex->add_create_options_with_check($3))
+ if (Lex->add_create_options_with_check($2))
MYSQL_YYABORT;
}
sp_name
trg_action_time
trg_event
ON
- remember_name /* $9 */
- { /* $10 */
+ remember_name /* $8 */
+ { /* $9 */
Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start();
}
- table_ident /* $11 */
+ table_ident /* $10 */
FOR_SYM
- remember_name /* $13 */
- { /* $14 */
+ remember_name /* $12 */
+ { /* $13 */
Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start();
}
EACH_SYM
@@ -16640,28 +16573,28 @@ trigger_tail:
{
Lex->trg_chistics.ordering_clause_begin= YYLIP->get_cpp_ptr();
}
- trigger_follows_precedes_clause /* $18 */
- { /* $19 */
+ trigger_follows_precedes_clause /* $17 */
+ { /* $18 */
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
if (lex->sphead)
my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"));
- lex->stmt_definition_begin= $2;
- lex->ident.str= $9;
- lex->ident.length= $13 - $9;
- lex->spname= $5;
- (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($18);
+ lex->stmt_definition_begin= $1;
+ lex->ident.str= $8;
+ lex->ident.length= $12 - $8;
+ lex->spname= $4;
+ (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($17);
lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr();
- if (!make_sp_head(thd, $5, TYPE_ENUM_TRIGGER))
+ if (!lex->make_sp_head(thd, $4, TYPE_ENUM_TRIGGER))
MYSQL_YYABORT;
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
- sp_proc_stmt /* $20 */
- { /* $21 */
+ sp_proc_stmt /* $19 */
+ { /* $20 */
LEX *lex= Lex;
sp_head *sp= lex->sphead;
@@ -16677,8 +16610,8 @@ trigger_tail:
sp_proc_stmt alternatives are not saving/restoring LEX, so
lex->query_tables can be wiped out.
*/
- if (!lex->select_lex.add_table_to_list(thd, $11,
- (LEX_STRING*) 0,
+ if (!lex->select_lex.add_table_to_list(thd, $10,
+ (LEX_CSTRING*) 0,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
MDL_SHARED_NO_WRITE))
@@ -16693,74 +16626,56 @@ trigger_tail:
**************************************************************************/
udf_tail:
- AGGREGATE_SYM udf_tail2 { thd->lex->udf.type= UDFTYPE_AGGREGATE; }
- | udf_tail2 { thd->lex->udf.type= UDFTYPE_FUNCTION; }
- ;
-
-udf_tail2:
- FUNCTION_SYM opt_if_not_exists ident
+ opt_if_not_exists ident
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
{
LEX *lex= thd->lex;
- if (lex->add_create_options_with_check($2))
+ if (lex->add_create_options_with_check($1))
MYSQL_YYABORT;
- if (is_native_function(thd, & $3))
- my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $3.str));
+ if (is_native_function(thd, & $2))
+ my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $2.str));
lex->sql_command= SQLCOM_CREATE_FUNCTION;
- lex->udf.name= $3;
- lex->udf.returns= (Item_result) $5;
- lex->udf.dl= $7.str;
+ lex->udf.name= $2;
+ lex->udf.returns= (Item_result) $4;
+ lex->udf.dl= $6.str;
}
;
-sf_tail:
- FUNCTION_SYM /* $1 */
- opt_if_not_exists /* $2 */
- sp_name /* $3 */
- '(' /* $4 */
- { /* $5 */
- LEX *lex= Lex;
- Lex_input_stream *lip= YYLIP;
- const char* tmp_param_begin;
-
- if (lex->add_create_options_with_check($2))
- MYSQL_YYABORT;
- lex->spname= $3;
-
- if (lex->sphead)
- my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"));
- if (!make_sp_head(thd, $3, TYPE_ENUM_FUNCTION))
- MYSQL_YYABORT;
-
- tmp_param_begin= lip->get_cpp_tok_start();
- tmp_param_begin++;
- lex->sphead->m_param_begin= tmp_param_begin;
- }
- sp_fdparam_list /* $6 */
- ')' /* $7 */
- { /* $8 */
- Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
- }
- RETURNS_SYM /* $9 */
- { /* $10 */
+sf_return_type:
+ RETURNS_SYM
+ {
LEX *lex= Lex;
- lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
+ lex->init_last_field(&lex->sphead->m_return_field_def,
+ &empty_clex_str,
thd->variables.collation_database);
}
- type_with_opt_collate /* $11 */
- { /* $12 */
- if (Lex->sphead->fill_field_definition(thd, Lex, Lex->last_field))
+ type_with_opt_collate
+ {
+ if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sf_tail:
+ opt_if_not_exists
+ sp_name
+ {
+ if (!Lex->make_sp_head_no_recursive(thd, $1, $2,
+ TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
}
- sp_c_chistics /* $13 */
- { /* $14 */
+ sp_parenthesized_fdparam_list
+ sf_return_type
+ sp_c_chistics
+ {
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
+ lex->sphead->set_chistics(lex->sp_chistics);
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
- sp_proc_stmt_in_returns_clause /* $15 */
+ sp_proc_stmt_in_returns_clause
{
LEX *lex= thd->lex;
sp_head *sp= lex->sphead;
@@ -16771,74 +16686,24 @@ sf_tail:
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->set_stmt_end(thd);
if (!(sp->m_flags & sp_head::HAS_RETURN))
- my_yyabort_error((ER_SP_NORETURN, MYF(0), sp->m_qname.str));
- if (is_native_function(thd, & sp->m_name))
- {
- /*
- This warning will be printed when
- [1] A client query is parsed,
- [2] A stored function is loaded by db_load_routine.
- Printing the warning for [2] is intentional, to cover the
- following scenario:
- - A user define a SF 'foo' using MySQL 5.N
- - An application uses select foo(), and works.
- - MySQL 5.{N+1} defines a new native function 'foo', as
- part of a new feature.
- - MySQL 5.{N+1} documentation is updated, and should mention
- that there is a potential incompatible change in case of
- existing stored function named 'foo'.
- - The user deploys 5.{N+1}. At this point, 'select foo()'
- means something different, and the user code is most likely
- broken (it's only safe if the code is 'select db.foo()').
- With a warning printed when the SF is loaded (which has to
- occur before the call), the warning will provide a hint
- explaining the root cause of a later failure of 'select foo()'.
- With no warning printed, the user code will fail with no
- apparent reason.
- Printing a warning each time db_load_routine is executed for
- an ambiguous function is annoying, since that can happen a lot,
- but in practice should not happen unless there *are* name
- collisions.
- If a collision exists, it should not be silenced but fixed.
- */
- push_warning_printf(thd,
- Sql_condition::WARN_LEVEL_NOTE,
- ER_NATIVE_FCT_NAME_COLLISION,
- ER_THD(thd, ER_NATIVE_FCT_NAME_COLLISION),
- sp->m_name.str);
- }
+ my_yyabort_error((ER_SP_NORETURN, MYF(0),
+ ErrConvDQName(sp).ptr()));
+ (void) is_native_function_with_warn(thd, &sp->m_name);
sp->restore_thd_mem_root(thd);
}
;
sp_tail:
- PROCEDURE_SYM opt_if_not_exists sp_name
+ opt_if_not_exists sp_name
{
- if (Lex->add_create_options_with_check($2))
- MYSQL_YYABORT;
-
- if (Lex->sphead)
- my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
-
- if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
+ if (!Lex->make_sp_head_no_recursive(thd, $1, $2,
+ TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
- Lex->spname= $3;
- }
- '('
- {
- const char* tmp_param_begin;
-
- tmp_param_begin= YYLIP->get_cpp_tok_start();
- tmp_param_begin++;
- Lex->sphead->m_param_begin= tmp_param_begin;
- }
- sp_pdparam_list
- ')'
- {
- Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
}
+ sp_parenthesized_pdparam_list
sp_c_chistics
{
+ Lex->sphead->set_chistics(Lex->sp_chistics);
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_proc_stmt
@@ -16946,7 +16811,7 @@ install:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_INSTALL_PLUGIN;
- lex->comment= null_lex_str;
+ lex->comment= null_clex_str;
lex->ident= $3;
}
;
@@ -16962,7 +16827,7 @@ uninstall:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
- lex->comment= null_lex_str;
+ lex->comment= null_clex_str;
lex->ident= $3;
}
;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
new file mode 100644
index 00000000000..95d60b463c2
--- /dev/null
+++ b/sql/sql_yacc_ora.yy
@@ -0,0 +1,17113 @@
+/*
+ Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2016, MariaDB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/* sql_yacc.yy */
+
+/**
+ @defgroup Parser Parser
+ @{
+*/
+
+%{
+#define YYLIP (& thd->m_parser_state->m_lip)
+#define YYPS (& thd->m_parser_state->m_yacc)
+#define YYCSCL (thd->variables.character_set_client)
+
+#define MYSQL_YACC
+#define YYINITDEPTH 100
+#define YYMAXDEPTH 3200 /* Because of 64K stack */
+#define Lex (thd->lex)
+
+#define Select Lex->current_select
+#include <my_global.h>
+#include "sql_priv.h"
+#include "sql_parse.h" /* comp_*_creator */
+#include "sql_table.h" /* primary_key_name */
+#include "sql_partition.h" /* mem_alloc_error, partition_info, HASH_PARTITION */
+#include "sql_acl.h" /* *_ACL */
+#include "sql_class.h" /* Key_part_spec, enum_filetype, Diag_condition_item_name */
+#include "slave.h"
+#include "lex_symbol.h"
+#include "item_create.h"
+#include "sp_head.h"
+#include "sp_rcontext.h"
+#include "sp.h"
+#include "sql_show.h"
+#include "sql_alter.h" // Sql_cmd_alter_table*
+#include "sql_truncate.h" // Sql_cmd_truncate_table
+#include "sql_admin.h" // Sql_cmd_analyze/Check..._table
+#include "sql_partition_admin.h" // Sql_cmd_alter_table_*_part.
+#include "sql_handler.h" // Sql_cmd_handler_*
+#include "sql_signal.h"
+#include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics
+#include "sql_cte.h"
+#include "sql_window.h"
+#include "item_windowfunc.h"
+#include "event_parse_data.h"
+#include "create_options.h"
+#include <myisam.h>
+#include <myisammrg.h>
+#include "keycaches.h"
+#include "set_var.h"
+#include "rpl_mi.h"
+#include "lex_token.h"
+#include "sql_lex.h"
+#include "sql_sequence.h"
+
+/* this is to get the bison compilation windows warnings out */
+#ifdef _MSC_VER
+/* warning C4065: switch statement contains 'default' but no 'case' labels */
+#pragma warning (disable : 4065)
+#endif
+
+int yylex(void *yylval, void *yythd);
+
+#define yyoverflow(A,B,C,D,E,F) \
+ { \
+ ulong val= *(F); \
+ if (my_yyoverflow((B), (D), &val)) \
+ { \
+ yyerror(thd, (char*) (A)); \
+ return 2; \
+ } \
+ else \
+ { \
+ *(F)= (YYSIZE_T)val; \
+ } \
+ }
+
+#define MYSQL_YYABORT \
+ do \
+ { \
+ LEX::cleanup_lex_after_parse_error(thd); \
+ YYABORT; \
+ } while (0)
+
+#define MYSQL_YYABORT_UNLESS(A) \
+ if (!(A)) \
+ { \
+ thd->parse_error(); \
+ MYSQL_YYABORT; \
+ }
+
+#define my_yyabort_error(A) \
+ do { my_error A; MYSQL_YYABORT; } while(0)
+
+#ifndef DBUG_OFF
+#define YYDEBUG 1
+#else
+#define YYDEBUG 0
+#endif
+
+
+/**
+ @brief Bison callback to report a syntax/OOM error
+
+ This function is invoked by the bison-generated parser
+ when a syntax error, a parse error or an out-of-memory
+ condition occurs. This function is not invoked when the
+ parser is requested to abort by semantic action code
+ by means of YYABORT or YYACCEPT macros. This is why these
+ macros should not be used (use MYSQL_YYABORT/MYSQL_YYACCEPT
+ instead).
+
+ The parser will abort immediately after invoking this callback.
+
+ This function is not for use in semantic actions and is internal to
+ the parser, as it performs some pre-return cleanup.
+ In semantic actions, please use thd->parse_error() or my_error to
+ push an error into the error stack and MYSQL_YYABORT
+ to abort from the parser.
+*/
+
+void ORAerror(THD *thd, const char *s)
+{
+ /*
+ Restore the original LEX if it was replaced when parsing
+ a stored procedure. We must ensure that a parsing error
+ does not leave any side effects in the THD.
+ */
+ LEX::cleanup_lex_after_parse_error(thd);
+
+ /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
+ if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
+ s= ER_THD(thd, ER_SYNTAX_ERROR);
+ thd->parse_error(s, 0);
+}
+
+
+
+
+#define bincmp_collation(X,Y) \
+ do \
+ { \
+ if (Lex->set_bincmp(X,Y)) \
+ MYSQL_YYABORT; \
+ } while(0)
+
+%}
+%union {
+ int num;
+ ulong ulong_num;
+ ulonglong ulonglong_number;
+ longlong longlong_number;
+ uint sp_instr_addr;
+
+ /* structs */
+ LEX_CSTRING lex_str;
+ LEX_SYMBOL symbol;
+ Lex_string_with_metadata_st lex_string_with_metadata;
+ struct sys_var_with_base variable;
+ Lex_string_with_pos_st lex_string_with_pos;
+ Lex_spblock_st spblock;
+ Lex_spblock_handlers_st spblock_handlers;
+ Lex_length_and_dec_st Lex_length_and_dec;
+ Lex_cast_type_st Lex_cast_type;
+ Lex_field_type_st Lex_field_type;
+ Lex_dyncol_type_st Lex_dyncol_type;
+ Lex_for_loop_st for_loop;
+ Lex_for_loop_bounds_st for_loop_bounds;
+ struct
+ {
+ LEX_CSTRING name;
+ uint offset;
+ } sp_cursor_name_and_offset;
+
+ /* pointers */
+ Create_field *create_field;
+ Spvar_definition *spvar_definition;
+ Row_definition_list *spvar_definition_list;
+ const Type_handler *type_handler;
+ CHARSET_INFO *charset;
+ Condition_information_item *cond_info_item;
+ DYNCALL_CREATE_DEF *dyncol_def;
+ Diagnostics_information *diag_info;
+ Item *item;
+ Item_num *item_num;
+ Item_param *item_param;
+ Key_part_spec *key_part;
+ LEX *lex;
+ sp_assignment_lex *assignment_lex;
+ class sp_lex_cursor *sp_cursor_stmt;
+ LEX_CSTRING *lex_str_ptr;
+ LEX_USER *lex_user;
+ List<Condition_information_item> *cond_info_list;
+ List<DYNCALL_CREATE_DEF> *dyncol_def_list;
+ List<Item> *item_list;
+ List<sp_assignment_lex> *sp_assignment_lex_list;
+ List<Statement_information_item> *stmt_info_list;
+ List<String> *string_list;
+ List<LEX_CSTRING> *lex_str_list;
+ Statement_information_item *stmt_info_item;
+ String *string;
+ TABLE_LIST *table_list;
+ Table_ident *table;
+ Qualified_column_ident *qualified_column_ident;
+ char *simple_string;
+ const char *const_simple_string;
+ chooser_compare_func_creator boolfunc2creator;
+ class my_var *myvar;
+ class sp_condition_value *spcondvalue;
+ class sp_head *sphead;
+ class sp_name *spname;
+ class sp_variable *spvar;
+ class With_clause *with_clause;
+ class Virtual_column_info *virtual_column;
+
+ handlerton *db_type;
+ st_select_lex *select_lex;
+ struct p_elem_val *p_elem_value;
+ class Window_frame *window_frame;
+ class Window_frame_bound *window_frame_bound;
+ udf_func *udf;
+ st_trg_execution_order trg_execution_order;
+
+ /* enums */
+ enum enum_view_suid view_suid;
+ enum sub_select_type unit_type;
+ enum Condition_information_item::Name cond_info_item_name;
+ enum enum_diag_condition_item_name diag_condition_item_name;
+ enum Diagnostics_information::Which_area diag_area;
+ enum Field::geometry_type geom_type;
+ enum enum_fk_option m_fk_option;
+ enum Item_udftype udf_type;
+ enum Key::Keytype key_type;
+ enum Statement_information_item::Name stmt_info_item_name;
+ enum enum_filetype filetype;
+ enum enum_tx_isolation tx_isolation;
+ enum enum_var_type var_type;
+ enum enum_yes_no_unknown m_yes_no_unk;
+ enum ha_choice choice;
+ enum ha_key_alg key_alg;
+ enum ha_rkey_function ha_rkey_mode;
+ enum index_hint_type index_hint;
+ enum interval_type interval, interval_time_st;
+ enum row_type row_type;
+ enum sp_variable::enum_mode spvar_mode;
+ enum thr_lock_type lock_type;
+ enum enum_mysql_timestamp_type date_time_type;
+ enum Window_frame_bound::Bound_precedence_type bound_precedence_type;
+ enum Window_frame::Frame_units frame_units;
+ enum Window_frame::Frame_exclusion frame_exclusion;
+ enum trigger_order_type trigger_action_order_type;
+ DDL_options_st object_ddl_options;
+}
+
+%{
+bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
+%}
+
+%pure-parser /* We have threads */
+%parse-param { THD *thd }
+%lex-param { THD *thd }
+/*
+ Currently there are 104 shift/reduce conflicts.
+ We should not introduce new conflicts any more.
+*/
+%expect 104
+
+/*
+ Comments for TOKENS.
+ For each token, please include in the same line a comment that contains
+ the following tags:
+ SQL-2011-N : Non Reserved keywird as per SQL-2011
+ SQL-2003-R : Reserved keyword as per SQL-2003
+ SQL-2003-N : Non Reserved keyword as per SQL-2003
+ SQL-1999-R : Reserved keyword as per SQL-1999
+ SQL-1999-N : Non Reserved keyword as per SQL-1999
+ MYSQL : MySQL extention (unspecified)
+ MYSQL-FUNC : MySQL extention, function
+ INTERNAL : Not a real token, lex optimization
+ OPERATOR : SQL operator
+ FUTURE-USE : Reserved for future use
+
+ This makes the code grep-able, and helps maintenance.
+*/
+
+%token ABORT_SYM /* INTERNAL (used in lex) */
+%token ACCESSIBLE_SYM
+%token ACTION /* SQL-2003-N */
+%token ADD /* SQL-2003-R */
+%token ADMIN_SYM /* SQL-2003-N */
+%token ADDDATE_SYM /* MYSQL-FUNC */
+%token AFTER_SYM /* SQL-2003-N */
+%token AGAINST
+%token AGGREGATE_SYM
+%token ALGORITHM_SYM
+%token ALL /* SQL-2003-R */
+%token ALTER /* SQL-2003-R */
+%token ALWAYS_SYM
+%token ANALYZE_SYM
+%token AND_AND_SYM /* OPERATOR */
+%token AND_SYM /* SQL-2003-R */
+%token ANY_SYM /* SQL-2003-R */
+%token AS /* SQL-2003-R */
+%token ASC /* SQL-2003-N */
+%token ASCII_SYM /* MYSQL-FUNC */
+%token ASENSITIVE_SYM /* FUTURE-USE */
+%token AT_SYM /* SQL-2003-R */
+%token ATOMIC_SYM /* SQL-2003-R */
+%token AUTHORS_SYM
+%token AUTOEXTEND_SIZE_SYM
+%token AUTO_INC
+%token AUTO_SYM
+%token AVG_ROW_LENGTH
+%token AVG_SYM /* SQL-2003-N */
+%token BACKUP_SYM
+%token BEFORE_SYM /* SQL-2003-N */
+%token BEGIN_SYM /* SQL-2003-R */
+%token BETWEEN_SYM /* SQL-2003-R */
+%token BIGINT /* SQL-2003-R */
+%token BINARY /* SQL-2003-R */
+%token BINLOG_SYM
+%token BIN_NUM
+%token BIT_AND /* MYSQL-FUNC */
+%token BIT_OR /* MYSQL-FUNC */
+%token BIT_SYM /* MYSQL-FUNC */
+%token BIT_XOR /* MYSQL-FUNC */
+%token BLOB_SYM /* SQL-2003-R */
+%token BLOCK_SYM
+%token BOOLEAN_SYM /* SQL-2003-R */
+%token BOOL_SYM
+%token BOTH /* SQL-2003-R */
+%token BTREE_SYM
+%token BY /* SQL-2003-R */
+%token BYTE_SYM
+%token CACHE_SYM
+%token CALL_SYM /* SQL-2003-R */
+%token CASCADE /* SQL-2003-N */
+%token CASCADED /* SQL-2003-R */
+%token CASE_SYM /* SQL-2003-R */
+%token CAST_SYM /* SQL-2003-R */
+%token CATALOG_NAME_SYM /* SQL-2003-N */
+%token CHAIN_SYM /* SQL-2003-N */
+%token CHANGE
+%token CHANGED
+%token CHARSET
+%token CHAR_SYM /* SQL-2003-R */
+%token CHECKPOINT_SYM
+%token CHECKSUM_SYM
+%token CHECK_SYM /* SQL-2003-R */
+%token CIPHER_SYM
+%token CLASS_ORIGIN_SYM /* SQL-2003-N */
+%token CLIENT_SYM
+%token CLOSE_SYM /* SQL-2003-R */
+%token CLOB /* SQL-2003-R */
+%token COALESCE /* SQL-2003-N */
+%token CODE_SYM
+%token COLLATE_SYM /* SQL-2003-R */
+%token COLLATION_SYM /* SQL-2003-N */
+%token COLUMNS
+%token COLUMN_ADD_SYM
+%token COLUMN_CHECK_SYM
+%token COLUMN_CREATE_SYM
+%token COLUMN_DELETE_SYM
+%token COLUMN_GET_SYM
+%token COLUMN_SYM /* SQL-2003-R */
+%token COLUMN_NAME_SYM /* SQL-2003-N */
+%token COMMENT_SYM
+%token COMMITTED_SYM /* SQL-2003-N */
+%token COMMIT_SYM /* SQL-2003-R */
+%token COMPACT_SYM
+%token COMPLETION_SYM
+%token COMPRESSED_SYM
+%token CONCURRENT
+%token CONDITION_SYM /* SQL-2003-R, SQL-2008-R */
+%token CONNECTION_SYM
+%token CONSISTENT_SYM
+%token CONSTRAINT /* SQL-2003-R */
+%token CONSTRAINT_CATALOG_SYM /* SQL-2003-N */
+%token CONSTRAINT_NAME_SYM /* SQL-2003-N */
+%token CONSTRAINT_SCHEMA_SYM /* SQL-2003-N */
+%token CONTAINS_SYM /* SQL-2003-N */
+%token CONTEXT_SYM
+%token CONTINUE_SYM /* SQL-2003-R */
+%token CONTRIBUTORS_SYM
+%token CONVERT_SYM /* SQL-2003-N */
+%token COUNT_SYM /* SQL-2003-N */
+%token CPU_SYM
+%token CREATE /* SQL-2003-R */
+%token CROSS /* SQL-2003-R */
+%token CUBE_SYM /* SQL-2003-R */
+%token CUME_DIST_SYM
+%token CURDATE /* MYSQL-FUNC */
+%token CURRENT_SYM /* SQL-2003-R */
+%token CURRENT_USER /* SQL-2003-R */
+%token CURRENT_ROLE /* SQL-2003-R */
+%token CURRENT_POS_SYM
+%token CURSOR_SYM /* SQL-2003-R */
+%token CURSOR_NAME_SYM /* SQL-2003-N */
+%token CURTIME /* MYSQL-FUNC */
+%token CYCLE_SYM
+%token DATABASE
+%token DATABASES
+%token DATAFILE_SYM
+%token DATA_SYM /* SQL-2003-N */
+%token DATETIME
+%token DATE_ADD_INTERVAL /* MYSQL-FUNC */
+%token DATE_SUB_INTERVAL /* MYSQL-FUNC */
+%token DATE_SYM /* SQL-2003-R */
+%token DAY_HOUR_SYM
+%token DAY_MICROSECOND_SYM
+%token DAY_MINUTE_SYM
+%token DAY_SECOND_SYM
+%token DAY_SYM /* SQL-2003-R */
+%token DEALLOCATE_SYM /* SQL-2003-R */
+%token DECIMAL_NUM
+%token DECIMAL_SYM /* SQL-2003-R */
+%token DECLARE_SYM /* SQL-2003-R */
+%token DECODE_SYM /* Oracle function, non-reserved */
+%token DEFAULT /* SQL-2003-R */
+%token DEFINER_SYM
+%token DELAYED_SYM
+%token DELAY_KEY_WRITE_SYM
+%token DELETE_SYM /* SQL-2003-R */
+%token DENSE_RANK_SYM
+%token DESC /* SQL-2003-N */
+%token DESCRIBE /* SQL-2003-R */
+%token DES_KEY_FILE
+%token DETERMINISTIC_SYM /* SQL-2003-R */
+%token DIAGNOSTICS_SYM /* SQL-2003-N */
+%token DIRECTORY_SYM
+%token DISABLE_SYM
+%token DISCARD
+%token DISK_SYM
+%token DISTINCT /* SQL-2003-R */
+%token DIV_SYM
+%token DOUBLE_SYM /* SQL-2003-R */
+%token DO_DOMAIN_IDS_SYM
+%token DO_SYM
+%token DOT_DOT_SYM
+%token DROP /* SQL-2003-R */
+%token DUAL_SYM
+%token DUMPFILE
+%token DUPLICATE_SYM
+%token DYNAMIC_SYM /* SQL-2003-R */
+%token EACH_SYM /* SQL-2003-R */
+%token ELSE /* SQL-2003-R */
+%token ELSEIF_SYM
+%token ELSIF_SYM /* Oracle, reserved in PL/SQL*/
+%token ENABLE_SYM
+%token ENCLOSED
+%token END /* SQL-2003-R */
+%token ENDS_SYM
+%token END_OF_INPUT /* INTERNAL */
+%token ENGINES_SYM
+%token ENGINE_SYM
+%token ENUM
+%token EQUAL_SYM /* OPERATOR */
+%token ERROR_SYM
+%token ERRORS
+%token ESCAPED
+%token ESCAPE_SYM /* SQL-2003-R */
+%token EVENTS_SYM
+%token EVENT_SYM
+%token EVERY_SYM /* SQL-2003-N */
+%token EXCHANGE_SYM
+%token EXAMINED_SYM
+%token EXCEPT_SYM /* SQL-2003-R */
+%token EXCLUDE_SYM /* SQL-2011-N */
+%token EXECUTE_SYM /* SQL-2003-R */
+%token EXCEPTION_SYM /* SQL-2003-N */
+%token EXISTS /* SQL-2003-R */
+%token EXIT_SYM
+%token EXPANSION_SYM
+%token EXPORT_SYM
+%token EXTENDED_SYM
+%token EXTENT_SIZE_SYM
+%token EXTRACT_SYM /* SQL-2003-N */
+%token FALSE_SYM /* SQL-2003-R */
+%token FAST_SYM
+%token FAULTS_SYM
+%token FETCH_SYM /* SQL-2003-R */
+%token FILE_SYM
+%token FIRST_VALUE_SYM /* SQL-2011 */
+%token FIRST_SYM /* SQL-2003-N */
+%token FIXED_SYM
+%token FLOAT_NUM
+%token FLOAT_SYM /* SQL-2003-R */
+%token FLUSH_SYM
+%token FOLLOWS_SYM /* MYSQL trigger*/
+%token FOLLOWING_SYM /* SQL-2011-N */
+%token FORCE_SYM
+%token FOREIGN /* SQL-2003-R */
+%token FOR_SYM /* SQL-2003-R */
+%token FORMAT_SYM
+%token FOUND_SYM /* SQL-2003-R */
+%token FROM
+%token FULL /* SQL-2003-R */
+%token FULLTEXT_SYM
+%token FUNCTION_SYM /* SQL-2003-R */
+%token GE
+%token GENERAL
+%token GENERATED_SYM
+%token GEOMETRYCOLLECTION
+%token GEOMETRY_SYM
+%token GET_FORMAT /* MYSQL-FUNC */
+%token GET_SYM /* SQL-2003-R */
+%token GLOBAL_SYM /* SQL-2003-R */
+%token GOTO_SYM /* Oracle, reserved in PL/SQL*/
+%token GRANT /* SQL-2003-R */
+%token GRANTS
+%token GROUP_SYM /* SQL-2003-R */
+%token GROUP_CONCAT_SYM
+%token LAG_SYM /* SQL-2011 */
+%token LEAD_SYM /* SQL-2011 */
+%token HANDLER_SYM
+%token HARD_SYM
+%token HASH_SYM
+%token HAVING /* SQL-2003-R */
+%token HELP_SYM
+%token HEX_NUM
+%token HEX_STRING
+%token HIGH_PRIORITY
+%token HOST_SYM
+%token HOSTS_SYM
+%token HOUR_MICROSECOND_SYM
+%token HOUR_MINUTE_SYM
+%token HOUR_SECOND_SYM
+%token HOUR_SYM /* SQL-2003-R */
+%token ID_SYM /* MYSQL */
+%token IDENT
+%token IDENTIFIED_SYM
+%token IDENT_QUOTED
+%token IF_SYM
+%token IGNORE_DOMAIN_IDS_SYM
+%token IGNORE_SYM
+%token IGNORE_SERVER_IDS_SYM
+%token IMMEDIATE_SYM /* SQL-2003-R */
+%token IMPORT
+%token INCREMENT_SYM
+%token INDEXES
+%token INDEX_SYM
+%token INFILE
+%token INITIAL_SIZE_SYM
+%token INNER_SYM /* SQL-2003-R */
+%token INOUT_SYM /* SQL-2003-R */
+%token INSENSITIVE_SYM /* SQL-2003-R */
+%token INSERT /* SQL-2003-R */
+%token INSERT_METHOD
+%token INSTALL_SYM
+%token INTERSECT_SYM /* SQL-2003-R */
+%token INTERVAL_SYM /* SQL-2003-R */
+%token INTO /* SQL-2003-R */
+%token INT_SYM /* SQL-2003-R */
+%token INVOKER_SYM
+%token IN_SYM /* SQL-2003-R */
+%token IO_SYM
+%token IPC_SYM
+%token IS /* SQL-2003-R */
+%token ISOLATION /* SQL-2003-R */
+%token ISOPEN_SYM /* Oracle-N */
+%token ISSUER_SYM
+%token ITERATE_SYM
+%token JOIN_SYM /* SQL-2003-R */
+%token JSON_SYM
+%token KEYS
+%token KEY_BLOCK_SIZE
+%token KEY_SYM /* SQL-2003-N */
+%token KILL_SYM
+%token LANGUAGE_SYM /* SQL-2003-R */
+%token LAST_SYM /* SQL-2003-N */
+%token LAST_VALUE
+%token LASTVAL_SYM /* PostgreSQL sequence function */
+%token LE /* OPERATOR */
+%token LEADING /* SQL-2003-R */
+%token LEAVES
+%token LEAVE_SYM
+%token LEFT /* SQL-2003-R */
+%token LESS_SYM
+%token LEVEL_SYM
+%token LEX_HOSTNAME
+%token LIKE /* SQL-2003-R */
+%token LIMIT
+%token LINEAR_SYM
+%token LINES
+%token LINESTRING
+%token LIST_SYM
+%token LOAD
+%token LOCAL_SYM /* SQL-2003-R */
+%token LOCATOR_SYM /* SQL-2003-N */
+%token LOCKS_SYM
+%token LOCK_SYM
+%token LOGFILE_SYM
+%token LOGS_SYM
+%token LONGBLOB
+%token LONGTEXT
+%token LONG_NUM
+%token LONG_SYM
+%token LOOP_SYM
+%token LOW_PRIORITY
+%token MASTER_CONNECT_RETRY_SYM
+%token MASTER_DELAY_SYM
+%token MASTER_GTID_POS_SYM
+%token MASTER_HOST_SYM
+%token MASTER_LOG_FILE_SYM
+%token MASTER_LOG_POS_SYM
+%token MASTER_PASSWORD_SYM
+%token MASTER_PORT_SYM
+%token MASTER_SERVER_ID_SYM
+%token MASTER_SSL_CAPATH_SYM
+%token MASTER_SSL_CA_SYM
+%token MASTER_SSL_CERT_SYM
+%token MASTER_SSL_CIPHER_SYM
+%token MASTER_SSL_CRL_SYM
+%token MASTER_SSL_CRLPATH_SYM
+%token MASTER_SSL_KEY_SYM
+%token MASTER_SSL_SYM
+%token MASTER_SSL_VERIFY_SERVER_CERT_SYM
+%token MASTER_SYM
+%token MASTER_USER_SYM
+%token MASTER_USE_GTID_SYM
+%token MASTER_HEARTBEAT_PERIOD_SYM
+%token MATCH /* SQL-2003-R */
+%token MAX_CONNECTIONS_PER_HOUR
+%token MAX_QUERIES_PER_HOUR
+%token MAX_ROWS
+%token MAX_SIZE_SYM
+%token MAX_SYM /* SQL-2003-N */
+%token MAX_UPDATES_PER_HOUR
+%token MAX_STATEMENT_TIME_SYM
+%token MAX_USER_CONNECTIONS_SYM
+%token MAXVALUE_SYM /* SQL-2003-N */
+%token MEDIUMBLOB
+%token MEDIUMINT
+%token MEDIUMTEXT
+%token MEDIUM_SYM
+%token MEMORY_SYM
+%token MERGE_SYM /* SQL-2003-R */
+%token MESSAGE_TEXT_SYM /* SQL-2003-N */
+%token MICROSECOND_SYM /* MYSQL-FUNC */
+%token MIGRATE_SYM
+%token MINUTE_MICROSECOND_SYM
+%token MINUTE_SECOND_SYM
+%token MINUTE_SYM /* SQL-2003-R */
+%token MINVALUE_SYM
+%token MIN_ROWS
+%token MIN_SYM /* SQL-2003-N */
+%token MODE_SYM
+%token MODIFIES_SYM /* SQL-2003-R */
+%token MODIFY_SYM
+%token MOD_SYM /* SQL-2003-N */
+%token MONTH_SYM /* SQL-2003-R */
+%token MULTILINESTRING
+%token MULTIPOINT
+%token MULTIPOLYGON
+%token MUTEX_SYM
+%token MYSQL_SYM
+%token MYSQL_ERRNO_SYM
+%token NAMES_SYM /* SQL-2003-N */
+%token NAME_SYM /* SQL-2003-N */
+%token NATIONAL_SYM /* SQL-2003-R */
+%token NATURAL /* SQL-2003-R */
+%token NCHAR_STRING
+%token NCHAR_SYM /* SQL-2003-R */
+%token NE /* OPERATOR */
+%token NEG
+%token NEW_SYM /* SQL-2003-R */
+%token NEXT_SYM /* SQL-2003-N */
+%token NEXTVAL_SYM /* PostgreSQL sequence function */
+%token NOCACHE_SYM
+%token NOCYCLE_SYM
+%token NODEGROUP_SYM
+%token NONE_SYM /* SQL-2003-R */
+%token NOT2_SYM
+%token NOT_SYM /* SQL-2003-R */
+%token NOTFOUND_SYM /* Oracle-R */
+%token NOW_SYM
+%token NO_SYM /* SQL-2003-R */
+%token NOMAXVALUE_SYM
+%token NOMINVALUE_SYM
+%token NO_WAIT_SYM
+%token NO_WRITE_TO_BINLOG
+%token NTILE_SYM
+%token NULL_SYM /* SQL-2003-R */
+%token NUM
+%token NUMBER_SYM /* SQL-2003-N */
+%token NUMERIC_SYM /* SQL-2003-R */
+%token NTH_VALUE_SYM /* SQL-2011 */
+%token NVARCHAR_SYM
+%token OF_SYM /* SQL-1992-R, Oracle-R */
+%token OFFSET_SYM
+%token OLD_PASSWORD_SYM
+%token ON /* SQL-2003-R */
+%token ONE_SYM
+%token ONLY_SYM /* SQL-2003-R */
+%token ONLINE_SYM
+%token OPEN_SYM /* SQL-2003-R */
+%token OPTIMIZE
+%token OPTIONS_SYM
+%token OPTION /* SQL-2003-N */
+%token OPTIONALLY
+%token OR2_SYM
+%token ORDER_SYM /* SQL-2003-R */
+%token OR_OR_SYM /* OPERATOR */
+%token OR_SYM /* SQL-2003-R */
+%token OTHERS_SYM /* SQL-2011-N */
+%token OUTER
+%token OUTFILE
+%token OUT_SYM /* SQL-2003-R */
+%token OVER_SYM
+%token OWNER_SYM
+%token PACK_KEYS_SYM
+%token PAGE_SYM
+%token PAGE_CHECKSUM_SYM
+%token PARAM_MARKER
+%token PARSER_SYM
+%token PARSE_VCOL_EXPR_SYM
+%token PARTIAL /* SQL-2003-N */
+%token PARTITION_SYM /* SQL-2003-R */
+%token PARTITIONS_SYM
+%token PARTITIONING_SYM
+%token PASSWORD_SYM
+%token PERCENT_RANK_SYM
+%token PERSISTENT_SYM
+%token PHASE_SYM
+%token PLUGINS_SYM
+%token PLUGIN_SYM
+%token POINT_SYM
+%token POLYGON
+%token PORT_SYM
+%token POSITION_SYM /* SQL-2003-N */
+%token PRECEDES_SYM /* MYSQL */
+%token PRECEDING_SYM /* SQL-2011-N */
+%token PRECISION /* SQL-2003-R */
+%token PREPARE_SYM /* SQL-2003-R */
+%token PRESERVE_SYM
+%token PREV_SYM
+%token PREVIOUS_SYM
+%token PRIMARY_SYM /* SQL-2003-R */
+%token PRIVILEGES /* SQL-2003-N */
+%token PROCEDURE_SYM /* SQL-2003-R */
+%token PROCESS
+%token PROCESSLIST_SYM
+%token PROFILE_SYM
+%token PROFILES_SYM
+%token PROXY_SYM
+%token PURGE
+%token QUARTER_SYM
+%token QUERY_SYM
+%token QUICK
+%token RAISE_SYM /* Oracle-PLSQL-R */
+%token RANGE_SYM /* SQL-2003-R */
+%token RANK_SYM
+%token RAW /* Oracle */
+%token READS_SYM /* SQL-2003-R */
+%token READ_ONLY_SYM
+%token READ_SYM /* SQL-2003-N */
+%token READ_WRITE_SYM
+%token REAL /* SQL-2003-R */
+%token REBUILD_SYM
+%token RECOVER_SYM
+%token RECURSIVE_SYM
+%token REDOFILE_SYM
+%token REDO_BUFFER_SIZE_SYM
+%token REDUNDANT_SYM
+%token REFERENCES /* SQL-2003-R */
+%token REGEXP
+%token RELAY
+%token RELAYLOG_SYM
+%token RELAY_LOG_FILE_SYM
+%token RELAY_LOG_POS_SYM
+%token RELAY_THREAD
+%token RELEASE_SYM /* SQL-2003-R */
+%token RELOAD
+%token REMOVE_SYM
+%token RENAME
+%token REORGANIZE_SYM
+%token REPAIR
+%token REPEATABLE_SYM /* SQL-2003-N */
+%token REPEAT_SYM /* MYSQL-FUNC */
+%token REPLACE /* MYSQL-FUNC */
+%token REPLICATION
+%token REQUIRE_SYM
+%token RESET_SYM
+%token RESTART_SYM
+%token RESIGNAL_SYM /* SQL-2003-R */
+%token RESOURCES
+%token RESTORE_SYM
+%token RESTRICT
+%token RESUME_SYM
+%token RETURNED_SQLSTATE_SYM /* SQL-2003-N */
+%token RETURNING_SYM
+%token RETURNS_SYM /* SQL-2003-R */
+%token RETURN_SYM /* SQL-2003-R */
+%token REUSE_SYM /* Oracle-R */
+%token REVERSE_SYM
+%token REVOKE /* SQL-2003-R */
+%token RIGHT /* SQL-2003-R */
+%token ROLE_SYM
+%token ROLLBACK_SYM /* SQL-2003-R */
+%token ROLLUP_SYM /* SQL-2003-R */
+%token ROUTINE_SYM /* SQL-2003-N */
+%token ROWCOUNT_SYM /* Oracle-N */
+%token ROW_SYM /* SQL-2003-R */
+%token ROWS_SYM /* SQL-2003-R */
+%token ROWTYPE_SYM /* Oracle-PLSQL-R */
+%token ROW_COUNT_SYM /* SQL-2003-N */
+%token ROW_FORMAT_SYM
+%token ROW_NUMBER_SYM
+%token RTREE_SYM
+%token SAVEPOINT_SYM /* SQL-2003-R */
+%token SCHEDULE_SYM
+%token SCHEMA_NAME_SYM /* SQL-2003-N */
+%token SECOND_MICROSECOND_SYM
+%token SECOND_SYM /* SQL-2003-R */
+%token SECURITY_SYM /* SQL-2003-N */
+%token SELECT_SYM /* SQL-2003-R */
+%token SENSITIVE_SYM /* FUTURE-USE */
+%token SEPARATOR_SYM
+%token SEQUENCE_SYM
+%token SERIALIZABLE_SYM /* SQL-2003-N */
+%token SERIAL_SYM
+%token SESSION_SYM /* SQL-2003-N */
+%token SERVER_SYM
+%token SERVER_OPTIONS
+%token SET /* SQL-2003-R */
+%token SETVAL_SYM /* PostgreSQL sequence function */
+%token SET_VAR
+%token SHARE_SYM
+%token SHIFT_LEFT /* OPERATOR */
+%token SHIFT_RIGHT /* OPERATOR */
+%token SHOW
+%token SHUTDOWN
+%token SIGNAL_SYM /* SQL-2003-R */
+%token SIGNED_SYM
+%token SIMPLE_SYM /* SQL-2003-N */
+%token SLAVE
+%token SLAVES
+%token SLAVE_POS_SYM
+%token SLOW
+%token SMALLINT /* SQL-2003-R */
+%token SNAPSHOT_SYM
+%token SOCKET_SYM
+%token SOFT_SYM
+%token SONAME_SYM
+%token SOUNDS_SYM
+%token SOURCE_SYM
+%token SPATIAL_SYM
+%token SPECIFIC_SYM /* SQL-2003-R */
+%token SQLEXCEPTION_SYM /* SQL-2003-R */
+%token SQLSTATE_SYM /* SQL-2003-R */
+%token SQLWARNING_SYM /* SQL-2003-R */
+%token SQL_BIG_RESULT
+%token SQL_BUFFER_RESULT
+%token SQL_CACHE_SYM
+%token SQL_CALC_FOUND_ROWS
+%token SQL_NO_CACHE_SYM
+%token SQL_SMALL_RESULT
+%token SQL_SYM /* SQL-2003-R */
+%token SQL_THREAD
+%token REF_SYSTEM_ID_SYM
+%token SSL_SYM
+%token STARTING
+%token STARTS_SYM
+%token START_SYM /* SQL-2003-R */
+%token STATEMENT_SYM
+%token STATS_AUTO_RECALC_SYM
+%token STATS_PERSISTENT_SYM
+%token STATS_SAMPLE_PAGES_SYM
+%token STATUS_SYM
+%token STDDEV_SAMP_SYM /* SQL-2003-N */
+%token STD_SYM
+%token STOP_SYM
+%token STORAGE_SYM
+%token STORED_SYM
+%token STRAIGHT_JOIN
+%token STRING_SYM
+%token SUBCLASS_ORIGIN_SYM /* SQL-2003-N */
+%token SUBDATE_SYM
+%token SUBJECT_SYM
+%token SUBPARTITIONS_SYM
+%token SUBPARTITION_SYM
+%token SUBSTRING /* SQL-2003-N */
+%token SUM_SYM /* SQL-2003-N */
+%token SUPER_SYM
+%token SUSPEND_SYM
+%token SWAPS_SYM
+%token SWITCHES_SYM
+%token SYSDATE
+%token TABLES
+%token TABLESPACE
+%token TABLE_REF_PRIORITY
+%token TABLE_SYM /* SQL-2003-R */
+%token TABLE_CHECKSUM_SYM
+%token TABLE_NAME_SYM /* SQL-2003-N */
+%token TEMPORARY /* SQL-2003-N */
+%token TEMPTABLE_SYM
+%token TERMINATED
+%token TEXT_STRING
+%token TEXT_SYM
+%token THAN_SYM
+%token THEN_SYM /* SQL-2003-R */
+%token TIES_SYM /* SQL-2011-N */
+%token TIMESTAMP /* SQL-2003-R */
+%token TIMESTAMP_ADD
+%token TIMESTAMP_DIFF
+%token TIME_SYM /* SQL-2003-R */
+%token TINYBLOB
+%token TINYINT
+%token TINYTEXT
+%token TO_SYM /* SQL-2003-R */
+%token TRAILING /* SQL-2003-R */
+%token TRANSACTION_SYM
+%token TRANSACTIONAL_SYM
+%token TRIGGERS_SYM
+%token TRIGGER_SYM /* SQL-2003-R */
+%token TRIM /* SQL-2003-N */
+%token TRUE_SYM /* SQL-2003-R */
+%token TRUNCATE_SYM
+%token TYPES_SYM
+%token TYPE_SYM /* SQL-2003-N */
+%token UDF_RETURNS_SYM
+%token ULONGLONG_NUM
+%token UNBOUNDED_SYM /* SQL-2011-N */
+%token UNCOMMITTED_SYM /* SQL-2003-N */
+%token UNDEFINED_SYM
+%token UNDERSCORE_CHARSET
+%token UNDOFILE_SYM
+%token UNDO_BUFFER_SIZE_SYM
+%token UNDO_SYM /* FUTURE-USE */
+%token UNICODE_SYM
+%token UNINSTALL_SYM
+%token UNION_SYM /* SQL-2003-R */
+%token UNIQUE_SYM
+%token UNKNOWN_SYM /* SQL-2003-R */
+%token UNLOCK_SYM
+%token UNSIGNED
+%token UNTIL_SYM
+%token UPDATE_SYM /* SQL-2003-R */
+%token UPGRADE_SYM
+%token USAGE /* SQL-2003-N */
+%token USER_SYM /* SQL-2003-R */
+%token USE_FRM
+%token USE_SYM
+%token USING /* SQL-2003-R */
+%token UTC_DATE_SYM
+%token UTC_TIMESTAMP_SYM
+%token UTC_TIME_SYM
+%token VALUES /* SQL-2003-R */
+%token VALUE_SYM /* SQL-2003-R */
+%token VARBINARY
+%token VARCHAR /* SQL-2003-R */
+%token VARCHAR2 /* Oracle */
+%token VARIABLES
+%token VARIANCE_SYM
+%token VARYING /* SQL-2003-R */
+%token VAR_SAMP_SYM
+%token VIA_SYM
+%token VIEW_SYM /* SQL-2003-N */
+%token VIRTUAL_SYM
+%token WAIT_SYM
+%token WARNINGS
+%token WEEK_SYM
+%token WEIGHT_STRING_SYM
+%token WHEN_SYM /* SQL-2003-R */
+%token WHERE /* SQL-2003-R */
+%token WINDOW_SYM
+%token WHILE_SYM
+%token WITH /* SQL-2003-R */
+%token WITH_CUBE_SYM /* INTERNAL */
+%token WITH_ROLLUP_SYM /* INTERNAL */
+%token WORK_SYM /* SQL-2003-N */
+%token WRAPPER_SYM
+%token WRITE_SYM /* SQL-2003-N */
+%token X509_SYM
+%token XA_SYM
+%token XML_SYM
+%token XOR
+%token YEAR_MONTH_SYM
+%token YEAR_SYM /* SQL-2003-R */
+%token ZEROFILL
+
+%token IMPOSSIBLE_ACTION /* To avoid warning for yyerrlab1 */
+
+%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT
+/* A dummy token to force the priority of table_ref production in a join. */
+%left TABLE_REF_PRIORITY
+%left SET_VAR
+%left OR_OR_SYM OR_SYM OR2_SYM
+%left XOR
+%left AND_SYM AND_AND_SYM
+%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
+%left '=' EQUAL_SYM GE '>' LE '<' NE IS LIKE REGEXP IN_SYM
+%left '|'
+%left '&'
+%left SHIFT_LEFT SHIFT_RIGHT
+%left '-' '+'
+%left '*' '/' DIV_SYM MOD_SYM
+%left '^'
+%left NEG '~'
+%right NOT_SYM NOT2_SYM
+%right BINARY COLLATE_SYM
+%left INTERVAL_SYM
+
+%type <lex_str>
+ IDENT IDENT_QUOTED DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
+ HEX_NUM HEX_STRING
+ LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text
+ IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
+ opt_component key_cache_name
+ sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
+ opt_constraint constraint opt_ident
+ label_declaration_oracle labels_declaration_oracle
+ ident_directly_assignable
+ sp_decl_ident
+ sp_block_label opt_place opt_db
+
+%type <lex_string_with_metadata>
+ TEXT_STRING
+ NCHAR_STRING
+
+%type <lex_str_ptr>
+ opt_table_alias
+
+%type <lex_string_with_pos>
+ ident ident_with_tok_start
+
+%type <table>
+ table_ident table_ident_nodb references xid
+ table_ident_opt_wild create_like
+
+%type <qualified_column_ident>
+ qualified_column_ident
+ optionally_qualified_column_ident
+
+%type <simple_string>
+ remember_name remember_end remember_tok_start
+ wild_and_where
+ colon_with_pos
+
+%type <const_simple_string>
+ field_length opt_field_length opt_field_length_default_1
+ opt_field_length_default_sp_param_varchar
+ opt_field_length_default_sp_param_char
+
+%type <string>
+ text_string hex_or_bin_String opt_gconcat_separator
+
+%type <type_handler> int_type real_type
+
+%type <Lex_field_type> type_with_opt_collate field_type
+ sp_param_type_with_opt_collate
+ sp_param_field_type
+ sp_param_field_type_string
+ field_type_numeric
+ field_type_string
+ field_type_lob
+ field_type_temporal
+ field_type_misc
+
+%type <Lex_dyncol_type> opt_dyncol_type dyncol_type
+ numeric_dyncol_type temporal_dyncol_type string_dyncol_type
+
+%type <create_field> field_spec column_def
+
+%type <geom_type> spatial_type
+
+%type <num>
+ order_dir lock_option
+ udf_type opt_local opt_no_write_to_binlog
+ opt_temporary all_or_any opt_distinct
+ opt_ignore_leaves fulltext_options union_option
+ opt_not
+ select_derived_init transaction_access_mode_types
+ opt_natural_language_mode opt_query_expansion
+ opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
+ ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
+ optional_flush_tables_arguments
+ opt_time_precision kill_type kill_option int_num
+ opt_default_time_precision
+ case_stmt_body opt_bin_mod
+ opt_if_exists_table_element opt_if_not_exists_table_element
+ opt_recursive
+
+%type <object_ddl_options>
+ create_or_replace
+ opt_if_not_exists
+ opt_if_exists
+
+/*
+ Bit field of MYSQL_START_TRANS_OPT_* flags.
+*/
+%type <num> opt_start_transaction_option_list
+%type <num> start_transaction_option_list
+%type <num> start_transaction_option
+
+%type <m_yes_no_unk>
+ opt_chain opt_release
+
+%type <m_fk_option>
+ delete_option
+
+%type <ulong_num>
+ ulong_num real_ulong_num merge_insert_types
+ ws_nweights
+ ws_level_flag_desc ws_level_flag_reverse ws_level_flags
+ opt_ws_levels ws_level_list ws_level_list_item ws_level_number
+ ws_level_range ws_level_list_or_range bool
+
+%type <ulonglong_number>
+ ulonglong_num real_ulonglong_num size_number
+
+%type <longlong_number>
+ longlong_num
+
+%type <choice> choice
+
+%type <lock_type>
+ replace_lock_option opt_low_priority insert_lock_option load_data_lock
+
+%type <item>
+ literal text_literal insert_ident order_ident temporal_literal
+ simple_ident expr opt_expr opt_else sum_expr in_sum_expr
+ variable variable_aux bool_pri
+ predicate bit_expr parenthesized_expr
+ table_wild simple_expr column_default_non_parenthesized_expr udf_expr
+ expr_or_default set_expr_or_default
+ geometry_function signed_literal expr_or_literal
+ opt_escape
+ sp_opt_default
+ simple_ident_nospvar simple_ident_q simple_ident_q2
+ field_or_var limit_option
+ part_func_expr
+ window_func_expr
+ window_func
+ simple_window_func
+ explicit_cursor_attr
+ function_call_keyword
+ function_call_nonkeyword
+ function_call_generic
+ function_call_conflict kill_expr
+ signal_allowed_expr
+ simple_target_specification
+ condition_number
+ reset_lex_expr
+
+%type <item_param> param_marker
+
+%type <item_num>
+ NUM_literal
+
+%type <item_list>
+ expr_list opt_udf_expr_list udf_expr_list when_list
+ ident_list ident_list_arg opt_expr_list
+ decode_when_list
+
+%type <sp_cursor_stmt>
+ sp_cursor_stmt_lex
+ sp_cursor_stmt
+
+%type <assignment_lex>
+ assignment_source_lex
+ assignment_source_expr
+ for_loop_bound_expr
+
+%type <sp_assignment_lex_list>
+ cursor_actual_parameters
+ opt_parenthesized_cursor_actual_parameters
+
+%type <var_type>
+ option_type opt_var_type opt_var_ident_type
+
+%type <key_type>
+ opt_unique constraint_key_type fulltext spatial
+
+%type <key_alg>
+ btree_or_rtree opt_key_algorithm_clause opt_USING_key_algorithm
+
+%type <string_list>
+ using_list opt_use_partition use_partition
+
+%type <key_part>
+ key_part
+
+%type <table_list>
+ join_table_list join_table
+ table_factor table_ref esc_table_ref
+ table_primary_ident table_primary_derived
+ select_derived derived_table_list
+ select_derived_union
+ derived_query_specification
+%type <date_time_type> date_time_type;
+%type <interval> interval
+
+%type <interval_time_st> interval_time_stamp
+
+%type <db_type> storage_engines known_storage_engines
+
+%type <row_type> row_types
+
+%type <tx_isolation> isolation_types
+
+%type <ha_rkey_mode> handler_rkey_mode
+
+%type <Lex_cast_type> cast_type cast_type_numeric cast_type_temporal
+
+%type <Lex_length_and_dec> precision opt_precision float_options
+
+%type <symbol> keyword keyword_sp
+ keyword_directly_assignable
+ keyword_directly_not_assignable
+ sp_decl_ident_keyword
+ keyword_sp_data_type
+ keyword_sp_not_data_type
+
+%type <lex_user> user grant_user grant_role user_or_role current_role
+ admin_option_for_role user_maybe_role
+
+%type <charset>
+ opt_collate
+ charset_name
+ charset_or_alias
+ charset_name_or_default
+ old_or_new_charset_name
+ old_or_new_charset_name_or_default
+ collation_name
+ collation_name_or_default
+ opt_load_data_charset
+ UNDERSCORE_CHARSET
+
+%type <variable> internal_variable_name
+ internal_variable_name_directly_assignable
+
+%type <select_lex> subselect
+ get_select_lex get_select_lex_derived
+ query_specification
+ query_term_union_not_ready
+ query_term_union_ready
+ query_expression_body
+ select_paren_derived
+
+%type <boolfunc2creator> comp_op
+
+%type <dyncol_def> dyncall_create_element
+
+%type <dyncol_def_list> dyncall_create_list
+
+%type <myvar> select_outvar
+
+%type <virtual_column> opt_check_constraint check_constraint virtual_column_func
+ column_default_expr
+%type <unit_type> unit_type_decl
+
+%type <NONE>
+ analyze_stmt_command
+ query verb_clause create change select do drop insert replace insert2
+ insert_values update delete truncate rename compound_statement
+ show describe load alter optimize keycache preload flush
+ reset purge commit rollback savepoint release
+ slave master_def master_defs master_file_def slave_until_opts
+ repair analyze opt_with_admin opt_with_admin_option
+ analyze_table_list analyze_table_elem_spec
+ opt_persistent_stat_clause persistent_stat_spec
+ persistent_column_stat_spec persistent_index_stat_spec
+ table_column_list table_index_list table_index_name
+ check start checksum
+ field_list field_list_item kill key_def constraint_def
+ keycache_list keycache_list_or_parts assign_to_keycache
+ assign_to_keycache_parts
+ preload_list preload_list_or_parts preload_keys preload_keys_parts
+ select_item_list select_item values_list no_braces
+ opt_limit_clause delete_limit_clause fields opt_values values
+ procedure_list procedure_list2 procedure_item
+ field_def handler opt_generated_always
+ opt_ignore opt_column opt_restrict
+ grant revoke set lock unlock string_list field_options field_option
+ field_opt_list opt_binary table_lock_list table_lock
+ ref_list opt_match_clause opt_on_update_delete use
+ opt_delete_options opt_delete_option varchar nchar nvarchar
+ opt_outer table_list table_name table_alias_ref_list table_alias_ref
+ opt_attribute opt_attribute_list attribute column_list column_list_id
+ opt_column_list grant_privileges grant_ident grant_list grant_option
+ object_privilege object_privilege_list user_list user_and_role_list
+ rename_list table_or_tables
+ clear_privileges flush_options flush_option
+ opt_flush_lock flush_lock flush_options_list
+ equal optional_braces
+ opt_mi_check_type opt_to mi_check_types
+ table_to_table_list table_to_table opt_table_list opt_as
+ handler_rkey_function handler_read_or_scan
+ single_multi table_wild_list table_wild_one opt_wild
+ union_clause union_list
+ subselect_start opt_and charset
+ subselect_end select_var_list select_var_list_init help
+ opt_extended_describe shutdown
+ opt_format_json
+ prepare prepare_src execute deallocate
+ statement sp_suid
+ sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
+ opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
+ view_list_opt view_list view_select
+ trigger_tail sp_tail sf_tail event_tail
+ udf_tail create_function_tail
+ install uninstall partition_entry binlog_base64_event
+ normal_key_options normal_key_opts all_key_opt
+ spatial_key_options fulltext_key_options normal_key_opt
+ fulltext_key_opt spatial_key_opt fulltext_key_opts spatial_key_opts
+ keep_gcc_happy
+ key_using_alg
+ part_column_list
+ server_def server_options_list server_option
+ definer_opt no_definer definer get_diagnostics
+ parse_vcol_expr vcol_opt_specifier vcol_opt_attribute
+ vcol_opt_attribute_list vcol_attribute
+ opt_serial_attribute opt_serial_attribute_list serial_attribute
+ explainable_command
+ set_assign
+ sf_tail_standalone
+ sp_tail_standalone
+END_OF_INPUT
+
+%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
+%type <NONE> sp_proc_stmt_statement sp_proc_stmt_return
+%type <NONE> sp_proc_stmt_compound_ok
+%type <NONE> sp_proc_stmt_if
+%type <NONE> sp_labeled_control sp_unlabeled_control
+%type <NONE> sp_labeled_block sp_unlabeled_block
+%type <NONE> sp_labelable_stmt
+%type <NONE> sp_proc_stmt_continue
+%type <NONE> sp_proc_stmt_exit
+%type <NONE> sp_proc_stmt_leave
+%type <NONE> sp_proc_stmt_iterate
+%type <NONE> sp_proc_stmt_goto
+%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
+%type <NONE> case_stmt_specification
+%type <NONE> loop_body while_body repeat_body
+
+%type <num> view_algorithm view_check_option
+%type <view_suid> view_suid opt_view_suid
+
+%type <num> sp_decl_idents sp_decl_idents_init_vars
+%type <num> sp_handler_type sp_hcond_list
+%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
+%type <spblock> sp_decl_body_list opt_sp_decl_body_list
+%type <spblock> sp_decl_non_handler sp_decl_non_handler_list
+%type <spblock> sp_decl_handler sp_decl_handler_list opt_sp_decl_handler_list
+%type <spblock_handlers> sp_block_statements_and_exceptions
+%type <sp_instr_addr> sp_instr_addr
+%type <sp_cursor_name_and_offset> sp_cursor_name_and_offset
+%type <num> opt_exception_clause exception_handlers
+%type <spname> sp_name opt_sp_name
+%type <spvar> sp_param_name sp_param_name_and_type
+%type <for_loop> sp_for_loop_index_and_bounds
+%type <for_loop_bounds> sp_for_loop_bounds
+%type <num> opt_sp_for_loop_direction
+%type <spvar_mode> sp_opt_inout
+%type <index_hint> index_hint_type
+%type <num> index_hint_clause normal_join inner_join
+%type <filetype> data_or_xml
+
+%type <NONE> signal_stmt resignal_stmt raise_stmt
+%type <diag_condition_item_name> signal_condition_information_item_name
+
+%type <trg_execution_order> trigger_follows_precedes_clause;
+%type <trigger_action_order_type> trigger_action_order;
+
+%type <diag_area> which_area;
+%type <diag_info> diagnostics_information;
+%type <stmt_info_item> statement_information_item;
+%type <stmt_info_item_name> statement_information_item_name;
+%type <stmt_info_list> statement_information;
+%type <cond_info_item> condition_information_item;
+%type <cond_info_item_name> condition_information_item_name;
+%type <cond_info_list> condition_information;
+
+%type <spvar_definition> row_field_name row_field_definition
+%type <spvar_definition_list> row_field_definition_list row_type_body
+
+%type <NONE> opt_window_clause window_def_list window_def window_spec
+%type <lex_str_ptr> window_name
+%type <NONE> opt_window_ref opt_window_frame_clause
+%type <frame_units> window_frame_units;
+%type <NONE> window_frame_extent;
+%type <frame_exclusion> opt_window_frame_exclusion;
+%type <window_frame_bound> window_frame_start window_frame_bound;
+
+
+%type <NONE>
+ '-' '+' '*' '/' '%' '(' ')'
+ ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
+ THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
+ ROLE_SYM
+
+%type <with_clause> opt_with_clause with_clause
+
+%type <lex_str_ptr> query_name
+
+%type <lex_str_list> opt_with_column_list
+
+%%
+
+
+/*
+ Indentation of grammar rules:
+
+rule: <-- starts at col 1
+ rule1a rule1b rule1c <-- starts at col 11
+ { <-- starts at col 11
+ code <-- starts at col 13, indentation is 2 spaces
+ }
+ | rule2a rule2b
+ {
+ code
+ }
+ ; <-- on a line by itself, starts at col 9
+
+ Also, please do not use any <TAB>, but spaces.
+ Having a uniform indentation in this file helps
+ code reviews, patches, merges, and make maintenance easier.
+ Tip: grep [[:cntrl:]] sql_yacc.yy
+ Thanks.
+*/
+
+query:
+ END_OF_INPUT
+ {
+ if (!thd->bootstrap &&
+ (!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
+ my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
+
+ thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
+ YYLIP->found_semicolon= NULL;
+ }
+ | verb_clause
+ {
+ Lex_input_stream *lip = YYLIP;
+
+ if ((thd->client_capabilities & CLIENT_MULTI_QUERIES) &&
+ lip->multi_statements &&
+ ! lip->eof())
+ {
+ /*
+ We found a well formed query, and multi queries are allowed:
+ - force the parser to stop after the ';'
+ - mark the start of the next query for the next invocation
+ of the parser.
+ */
+ lip->next_state= MY_LEX_END;
+ lip->found_semicolon= lip->get_ptr();
+ }
+ else
+ {
+ /* Single query, terminated. */
+ lip->found_semicolon= NULL;
+ }
+ }
+ ';'
+ opt_end_of_input
+ | verb_clause END_OF_INPUT
+ {
+ /* Single query, not terminated. */
+ YYLIP->found_semicolon= NULL;
+ }
+ ;
+
+opt_end_of_input:
+ /* empty */
+ | END_OF_INPUT
+ ;
+
+verb_clause:
+ statement
+ | compound_statement
+ ;
+
+/* Verb clauses, except begin and compound_statement */
+statement:
+ alter
+ | analyze
+ | analyze_stmt_command
+ | binlog_base64_event
+ | call
+ | change
+ | check
+ | checksum
+ | commit
+ | create
+ | deallocate
+ | delete
+ | describe
+ | do
+ | drop
+ | execute
+ | flush
+ | get_diagnostics
+ | grant
+ | handler
+ | help
+ | insert
+ | install
+ | keep_gcc_happy
+ | keycache
+ | kill
+ | load
+ | lock
+ | optimize
+ | parse_vcol_expr
+ | partition_entry
+ | preload
+ | prepare
+ | purge
+ | raise_stmt
+ | release
+ | rename
+ | repair
+ | replace
+ | reset
+ | resignal_stmt
+ | revoke
+ | rollback
+ | savepoint
+ | select
+ | set
+ | set_assign
+ | signal_stmt
+ | show
+ | shutdown
+ | slave
+ | start
+ | truncate
+ | uninstall
+ | unlock
+ | update
+ | use
+ | xa
+ ;
+
+deallocate:
+ deallocate_or_drop PREPARE_SYM ident
+ {
+ LEX *lex= thd->lex;
+ lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
+ lex->prepared_stmt_name= $3;
+ }
+ ;
+
+deallocate_or_drop:
+ DEALLOCATE_SYM
+ | DROP
+ ;
+
+prepare:
+ PREPARE_SYM ident FROM prepare_src
+ {
+ LEX *lex= thd->lex;
+ if (lex->table_or_sp_used())
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
+ "PREPARE..FROM"));
+ lex->sql_command= SQLCOM_PREPARE;
+ lex->prepared_stmt_name= $2;
+ }
+ ;
+
+prepare_src:
+ { Lex->expr_allows_subselect= false; }
+ expr
+ {
+ Lex->prepared_stmt_code= $2;
+ Lex->expr_allows_subselect= true;
+ }
+ ;
+
+execute:
+ EXECUTE_SYM ident
+ {
+ LEX *lex= thd->lex;
+ lex->sql_command= SQLCOM_EXECUTE;
+ lex->prepared_stmt_name= $2;
+ }
+ execute_using
+ {}
+ | EXECUTE_SYM IMMEDIATE_SYM prepare_src
+ {
+ if (Lex->table_or_sp_used())
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
+ "EXECUTE IMMEDIATE"));
+ Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
+ }
+ execute_using
+ {}
+ ;
+
+execute_using:
+ /* nothing */
+ | USING { Lex->expr_allows_subselect= false; }
+ execute_var_list
+ {
+ if (Lex->table_or_sp_used())
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
+ "EXECUTE..USING"));
+ Lex->expr_allows_subselect= true;
+ }
+ ;
+
+execute_var_list:
+ execute_var_list ',' execute_var_ident
+ | execute_var_ident
+ ;
+
+execute_var_ident:
+ expr_or_default
+ {
+ if (Lex->prepared_stmt_params.push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/* help */
+
+help:
+ HELP_SYM
+ {
+ if (Lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HELP"));
+ }
+ ident_or_text
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_HELP;
+ lex->help_arg= $3.str;
+ }
+ ;
+
+/* change master */
+
+change:
+ CHANGE MASTER_SYM optional_connection_name TO_SYM
+ {
+ Lex->sql_command = SQLCOM_CHANGE_MASTER;
+ }
+ master_defs
+ {}
+ ;
+
+master_defs:
+ master_def
+ | master_defs ',' master_def
+ ;
+
+master_def:
+ MASTER_HOST_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.host = $3.str;
+ }
+ | MASTER_USER_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.user = $3.str;
+ }
+ | MASTER_PASSWORD_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.password = $3.str;
+ }
+ | MASTER_PORT_SYM '=' ulong_num
+ {
+ Lex->mi.port = $3;
+ }
+ | MASTER_CONNECT_RETRY_SYM '=' ulong_num
+ {
+ Lex->mi.connect_retry = $3;
+ }
+ | MASTER_DELAY_SYM '=' ulong_num
+ {
+ if ($3 > MASTER_DELAY_MAX)
+ {
+ my_error(ER_MASTER_DELAY_VALUE_OUT_OF_RANGE, MYF(0),
+ (ulong) $3, (ulong) MASTER_DELAY_MAX);
+ }
+ else
+ Lex->mi.sql_delay = $3;
+ }
+ | MASTER_SSL_SYM '=' ulong_num
+ {
+ Lex->mi.ssl= $3 ?
+ LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
+ }
+ | MASTER_SSL_CA_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_ca= $3.str;
+ }
+ | MASTER_SSL_CAPATH_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_capath= $3.str;
+ }
+ | MASTER_SSL_CERT_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_cert= $3.str;
+ }
+ | MASTER_SSL_CIPHER_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_cipher= $3.str;
+ }
+ | MASTER_SSL_KEY_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_key= $3.str;
+ }
+ | MASTER_SSL_VERIFY_SERVER_CERT_SYM '=' ulong_num
+ {
+ Lex->mi.ssl_verify_server_cert= $3 ?
+ LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
+ }
+ | MASTER_SSL_CRL_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_crl= $3.str;
+ }
+ | MASTER_SSL_CRLPATH_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.ssl_crlpath= $3.str;
+ }
+
+ | MASTER_HEARTBEAT_PERIOD_SYM '=' NUM_literal
+ {
+ Lex->mi.heartbeat_period= (float) $3->val_real();
+ if (Lex->mi.heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD ||
+ Lex->mi.heartbeat_period < 0.0)
+ my_yyabort_error((ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0),
+ SLAVE_MAX_HEARTBEAT_PERIOD));
+
+ if (Lex->mi.heartbeat_period > slave_net_timeout)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
+ ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
+ }
+ if (Lex->mi.heartbeat_period < 0.001)
+ {
+ if (Lex->mi.heartbeat_period != 0.0)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN,
+ ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
+ Lex->mi.heartbeat_period= 0.0;
+ }
+ Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_DISABLE;
+ }
+ Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+ }
+ | IGNORE_SERVER_IDS_SYM '=' '(' ignore_server_id_list ')'
+ {
+ Lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+ }
+ | DO_DOMAIN_IDS_SYM '=' '(' do_domain_id_list ')'
+ {
+ Lex->mi.repl_do_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+ }
+ | IGNORE_DOMAIN_IDS_SYM '=' '(' ignore_domain_id_list ')'
+ {
+ Lex->mi.repl_ignore_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
+ }
+ |
+ master_file_def
+ ;
+
+ignore_server_id_list:
+ /* Empty */
+ | ignore_server_id
+ | ignore_server_id_list ',' ignore_server_id
+ ;
+
+ignore_server_id:
+ ulong_num
+ {
+ insert_dynamic(&Lex->mi.repl_ignore_server_ids, (uchar*) &($1));
+ }
+ ;
+
+do_domain_id_list:
+ /* Empty */
+ | do_domain_id
+ | do_domain_id_list ',' do_domain_id
+ ;
+
+do_domain_id:
+ ulong_num
+ {
+ insert_dynamic(&Lex->mi.repl_do_domain_ids, (uchar*) &($1));
+ }
+ ;
+
+ignore_domain_id_list:
+ /* Empty */
+ | ignore_domain_id
+ | ignore_domain_id_list ',' ignore_domain_id
+ ;
+
+ignore_domain_id:
+ ulong_num
+ {
+ insert_dynamic(&Lex->mi.repl_ignore_domain_ids, (uchar*) &($1));
+ }
+ ;
+
+master_file_def:
+ MASTER_LOG_FILE_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.log_file_name = $3.str;
+ }
+ | MASTER_LOG_POS_SYM '=' ulonglong_num
+ {
+ /*
+ If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
+ instead of causing subsequent errors.
+ We need to do it in this file, because only there we know that
+ MASTER_LOG_POS has been explicitly specified. On the contrary
+ in change_master() (sql_repl.cc) we cannot distinguish between 0
+ (MASTER_LOG_POS explicitly specified as 0) and 0 (unspecified),
+ whereas we want to distinguish (specified 0 means "read the binlog
+ from 0" (4 in fact), unspecified means "don't change the position
+ (keep the preceding value)").
+ */
+ Lex->mi.pos= MY_MAX(BIN_LOG_HEADER_SIZE, $3);
+ }
+ | RELAY_LOG_FILE_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.relay_log_name = $3.str;
+ }
+ | RELAY_LOG_POS_SYM '=' ulong_num
+ {
+ Lex->mi.relay_log_pos = $3;
+ /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
+ Lex->mi.relay_log_pos= MY_MAX(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
+ }
+ | MASTER_USE_GTID_SYM '=' CURRENT_POS_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS;
+ }
+ | MASTER_USE_GTID_SYM '=' SLAVE_POS_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS;
+ }
+ | MASTER_USE_GTID_SYM '=' NO_SYM
+ {
+ if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
+ Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO;
+ }
+ ;
+
+optional_connection_name:
+ /* empty */
+ {
+ LEX *lex= thd->lex;
+ lex->mi.connection_name= null_clex_str;
+ }
+ | connection_name
+ ;
+
+connection_name:
+ TEXT_STRING_sys
+ {
+ Lex->mi.connection_name= $1;
+#ifdef HAVE_REPLICATION
+ if (check_master_connection_name(&$1))
+ my_yyabort_error((ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME"));
+#endif
+ }
+ ;
+
+/* create a table */
+
+create:
+ create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident
+ {
+ LEX *lex= thd->lex;
+ lex->create_info.init();
+ if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4))
+ MYSQL_YYABORT;
+ if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
+ MYSQL_YYABORT;
+ lex->alter_info.reset();
+ /*
+ For CREATE TABLE we should not open the table even if it exists.
+ If the table exists, we should either not create it or replace it
+ */
+ lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
+ lex->create_info.default_table_charset= NULL;
+ lex->name= null_clex_str;
+ lex->create_last_non_select_table= lex->last_table();
+ }
+ create_body
+ {
+ LEX *lex= thd->lex;
+ lex->current_select= &lex->select_lex;
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
+ {
+ lex->create_info.use_default_db_type(thd);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
+ hton_name(lex->create_info.db_type)->str,
+ $5->table.str);
+ }
+ create_table_set_open_action_and_adjust_tables(lex);
+ }
+ | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident
+ {
+ LEX *lex= thd->lex;
+ lex->create_info.init();
+ if (lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, $1 | $4))
+ MYSQL_YYABORT;
+
+ if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_UPDATING,
+ TL_WRITE, MDL_EXCLUSIVE))
+ MYSQL_YYABORT;
+
+ /*
+ For CREATE TABLE, an non-existing table is not an error.
+ Instruct open_tables() to just take an MDL lock if the
+ table does not exist.
+ */
+ lex->alter_info.reset();
+ lex->query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
+ lex->name= null_clex_str;
+ lex->create_last_non_select_table= lex->last_table();
+ if (!(lex->create_info.seq_create_info= new (thd->mem_root)
+ sequence_definition()))
+ MYSQL_YYABORT;
+ }
+ opt_sequence opt_create_table_options
+ {
+ LEX *lex= thd->lex;
+
+ if (lex->create_info.seq_create_info->check_and_adjust(1))
+ {
+ my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
+ lex->select_lex.table_list.first->db,
+ lex->select_lex.table_list.first->table_name);
+ MYSQL_YYABORT;
+ }
+
+ /* No fields specified, generate them */
+ if (prepare_sequence_fields(thd, &lex->alter_info.create_list))
+ MYSQL_YYABORT;
+
+ /* CREATE SEQUENCE always creates a sequence */
+ Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
+ Lex->create_info.sequence= 1;
+
+ lex->current_select= &lex->select_lex;
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
+ {
+ lex->create_info.use_default_db_type(thd);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
+ hton_name(lex->create_info.db_type)->str,
+ $5->table.str);
+ }
+ create_table_set_open_action_and_adjust_tables(lex);
+ }
+ | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident
+ opt_key_algorithm_clause
+ ON table_ident
+ {
+ if (Lex->add_create_index_prepare($8))
+ MYSQL_YYABORT;
+ if (Lex->add_create_index($2, &$5, $6, $1 | $4))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options
+ opt_index_lock_algorithm { }
+ | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident
+ ON table_ident
+ {
+ if (Lex->add_create_index_prepare($7))
+ MYSQL_YYABORT;
+ if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' fulltext_key_options
+ opt_index_lock_algorithm { }
+ | create_or_replace spatial INDEX_SYM opt_if_not_exists ident
+ ON table_ident
+ {
+ if (Lex->add_create_index_prepare($7))
+ MYSQL_YYABORT;
+ if (Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, $1 | $4))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' spatial_key_options
+ opt_index_lock_algorithm { }
+ | create_or_replace DATABASE opt_if_not_exists ident
+ {
+ Lex->create_info.default_table_charset= NULL;
+ Lex->create_info.used_fields= 0;
+ }
+ opt_create_database_options
+ {
+ LEX *lex=Lex;
+ if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $1 | $3))
+ MYSQL_YYABORT;
+ lex->name= $4;
+ }
+ | create_or_replace definer_opt opt_view_suid VIEW_SYM
+ opt_if_not_exists table_ident
+ {
+ if (Lex->add_create_view(thd, $1 | $5,
+ DTYPE_ALGORITHM_UNDEFINED, $3, $6))
+ MYSQL_YYABORT;
+ }
+ view_list_opt AS view_select
+ { }
+ | create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM
+ opt_if_not_exists table_ident
+ {
+ if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7))
+ MYSQL_YYABORT;
+ }
+ view_list_opt AS view_select
+ { }
+ | create_or_replace definer_opt TRIGGER_SYM
+ { Lex->create_info.set($1); }
+ trigger_tail
+ { }
+ | create_or_replace definer_opt PROCEDURE_SYM
+ { Lex->create_info.set($1); }
+ sp_tail_standalone
+ { }
+ | create_or_replace definer_opt EVENT_SYM
+ { Lex->create_info.set($1); }
+ event_tail
+ { }
+ | create_or_replace definer FUNCTION_SYM
+ { Lex->create_info.set($1); }
+ sf_tail_standalone
+ { }
+ | create_or_replace no_definer FUNCTION_SYM
+ { Lex->create_info.set($1); }
+ create_function_tail
+ { }
+ | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
+ {
+ Lex->create_info.set($1);
+ Lex->udf.type= UDFTYPE_AGGREGATE;
+ }
+ udf_tail
+ { }
+ | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list
+ opt_require_clause opt_resource_options
+ {
+ if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))
+ MYSQL_YYABORT;
+ }
+ | create_or_replace ROLE_SYM opt_if_not_exists
+ clear_privileges role_list opt_with_admin
+ {
+ if (Lex->set_command_with_check(SQLCOM_CREATE_ROLE, $1 | $3))
+ MYSQL_YYABORT;
+ }
+ | CREATE LOGFILE_SYM GROUP_SYM logfile_group_info
+ {
+ Lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP;
+ }
+ | CREATE TABLESPACE tablespace_info
+ {
+ Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
+ }
+ | create_or_replace { Lex->set_command(SQLCOM_CREATE_SERVER, $1); }
+ server_def
+ { }
+ ;
+
+create_function_tail:
+ sf_tail_standalone { }
+ | udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; }
+ ;
+
+opt_sequence:
+ /* empty */ { }
+ | sequence_defs
+ ;
+
+sequence_defs:
+ sequence_def
+ | sequence_defs sequence_def
+ ;
+
+sequence_def:
+ MINVALUE_SYM opt_equal longlong_num
+ {
+ Lex->create_info.seq_create_info->min_value= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ }
+ | NO_SYM MINVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ }
+ | NOMINVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_min_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_min_value;
+ }
+ | MAXVALUE_SYM opt_equal longlong_num
+ {
+ Lex->create_info.seq_create_info->max_value= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ }
+ | NO_SYM MAXVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ }
+ | NOMAXVALUE_SYM
+ {
+ if (Lex->create_info.seq_create_info->used_fields & seq_field_used_max_value)
+ MYSQL_YYABORT;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_max_value;
+ }
+ | START_SYM opt_with longlong_num
+ {
+ Lex->create_info.seq_create_info->start= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_start;
+ }
+ | INCREMENT_SYM opt_by longlong_num
+ {
+ Lex->create_info.seq_create_info->increment= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_increment;
+ }
+ | CACHE_SYM opt_equal longlong_num
+ {
+ Lex->create_info.seq_create_info->cache= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
+ }
+ | NOCACHE_SYM
+ {
+ Lex->create_info.seq_create_info->cache= 0;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cache;
+ }
+ | CYCLE_SYM
+ {
+ Lex->create_info.seq_create_info->cycle= 1;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
+ }
+ | NOCYCLE_SYM
+ {
+ Lex->create_info.seq_create_info->cycle= 0;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_cycle;
+ }
+ | RESTART_SYM
+ {
+ if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
+ YYABORT;
+ }
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart;
+ }
+ | RESTART_SYM opt_with longlong_num
+ {
+ if (Lex->sql_command != SQLCOM_ALTER_SEQUENCE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, "RESTART");
+ YYABORT;
+ }
+ Lex->create_info.seq_create_info->restart= $3;
+ Lex->create_info.seq_create_info->used_fields|= seq_field_used_restart | seq_field_used_restart_value;
+ }
+ ;
+
+server_def:
+ SERVER_SYM opt_if_not_exists ident_or_text
+ {
+ if (Lex->add_create_options_with_check($2))
+ MYSQL_YYABORT;
+ Lex->server_options.reset($3);
+ }
+ FOREIGN DATA_SYM WRAPPER_SYM ident_or_text
+ OPTIONS_SYM '(' server_options_list ')'
+ { Lex->server_options.scheme= $8; }
+ ;
+
+server_options_list:
+ server_option
+ | server_options_list ',' server_option
+ ;
+
+server_option:
+ USER_SYM TEXT_STRING_sys
+ {
+ MYSQL_YYABORT_UNLESS(Lex->server_options.username.str == 0);
+ Lex->server_options.username= $2;
+ }
+ | HOST_SYM TEXT_STRING_sys
+ {
+ MYSQL_YYABORT_UNLESS(Lex->server_options.host.str == 0);
+ Lex->server_options.host= $2;
+ my_casedn_str(system_charset_info,
+ (char*) Lex->server_options.host.str);
+ }
+ | DATABASE TEXT_STRING_sys
+ {
+ MYSQL_YYABORT_UNLESS(Lex->server_options.db.str == 0);
+ Lex->server_options.db= $2;
+ }
+ | OWNER_SYM TEXT_STRING_sys
+ {
+ MYSQL_YYABORT_UNLESS(Lex->server_options.owner.str == 0);
+ Lex->server_options.owner= $2;
+ }
+ | PASSWORD_SYM TEXT_STRING_sys
+ {
+ MYSQL_YYABORT_UNLESS(Lex->server_options.password.str == 0);
+ Lex->server_options.password= $2;
+ }
+ | SOCKET_SYM TEXT_STRING_sys
+ {
+ MYSQL_YYABORT_UNLESS(Lex->server_options.socket.str == 0);
+ Lex->server_options.socket= $2;
+ }
+ | PORT_SYM ulong_num
+ {
+ Lex->server_options.port= $2;
+ }
+ ;
+
+event_tail:
+ remember_name opt_if_not_exists sp_name
+ {
+ LEX *lex=Lex;
+
+ lex->stmt_definition_begin= $1;
+ if (lex->add_create_options_with_check($2))
+ MYSQL_YYABORT;
+ if (!(lex->event_parse_data= Event_parse_data::new_instance(thd)))
+ MYSQL_YYABORT;
+ lex->event_parse_data->identifier= $3;
+ lex->event_parse_data->on_completion=
+ Event_parse_data::ON_COMPLETION_DROP;
+
+ lex->sql_command= SQLCOM_CREATE_EVENT;
+ /* We need that for disallowing subqueries */
+ }
+ ON SCHEDULE_SYM ev_schedule_time
+ opt_ev_on_completion
+ opt_ev_status
+ opt_ev_comment
+ DO_SYM ev_sql_stmt
+ {
+ /*
+ sql_command is set here because some rules in ev_sql_stmt
+ can overwrite it
+ */
+ Lex->sql_command= SQLCOM_CREATE_EVENT;
+ }
+ ;
+
+ev_schedule_time:
+ EVERY_SYM expr interval
+ {
+ Lex->event_parse_data->item_expression= $2;
+ Lex->event_parse_data->interval= $3;
+ }
+ ev_starts
+ ev_ends
+ | AT_SYM expr
+ {
+ Lex->event_parse_data->item_execute_at= $2;
+ }
+ ;
+
+opt_ev_status:
+ /* empty */ { $$= 0; }
+ | ENABLE_SYM
+ {
+ Lex->event_parse_data->status= Event_parse_data::ENABLED;
+ Lex->event_parse_data->status_changed= true;
+ $$= 1;
+ }
+ | DISABLE_SYM ON SLAVE
+ {
+ Lex->event_parse_data->status= Event_parse_data::SLAVESIDE_DISABLED;
+ Lex->event_parse_data->status_changed= true;
+ $$= 1;
+ }
+ | DISABLE_SYM
+ {
+ Lex->event_parse_data->status= Event_parse_data::DISABLED;
+ Lex->event_parse_data->status_changed= true;
+ $$= 1;
+ }
+ ;
+
+ev_starts:
+ /* empty */
+ {
+ Item *item= new (thd->mem_root) Item_func_now_local(thd, 0);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ Lex->event_parse_data->item_starts= item;
+ }
+ | STARTS_SYM expr
+ {
+ Lex->event_parse_data->item_starts= $2;
+ }
+ ;
+
+ev_ends:
+ /* empty */
+ | ENDS_SYM expr
+ {
+ Lex->event_parse_data->item_ends= $2;
+ }
+ ;
+
+opt_ev_on_completion:
+ /* empty */ { $$= 0; }
+ | ev_on_completion
+ ;
+
+ev_on_completion:
+ ON COMPLETION_SYM opt_not PRESERVE_SYM
+ {
+ Lex->event_parse_data->on_completion= $3
+ ? Event_parse_data::ON_COMPLETION_DROP
+ : Event_parse_data::ON_COMPLETION_PRESERVE;
+ $$= 1;
+ }
+ ;
+
+opt_ev_comment:
+ /* empty */ { $$= 0; }
+ | COMMENT_SYM TEXT_STRING_sys
+ {
+ Lex->comment= Lex->event_parse_data->comment= $2;
+ $$= 1;
+ }
+ ;
+
+ev_sql_stmt:
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= YYLIP;
+
+ /*
+ This stops the following :
+ - CREATE EVENT ... DO CREATE EVENT ...;
+ - ALTER EVENT ... DO CREATE EVENT ...;
+ - CREATE EVENT ... DO ALTER EVENT DO ....;
+ - CREATE PROCEDURE ... BEGIN CREATE EVENT ... END|
+ This allows:
+ - CREATE EVENT ... DO DROP EVENT yyy;
+ - CREATE EVENT ... DO ALTER EVENT yyy;
+ (the nested ALTER EVENT can have anything but DO clause)
+ - ALTER EVENT ... DO ALTER EVENT yyy;
+ (the nested ALTER EVENT can have anything but DO clause)
+ - ALTER EVENT ... DO DROP EVENT yyy;
+ - CREATE PROCEDURE ... BEGIN ALTER EVENT ... END|
+ (the nested ALTER EVENT can have anything but DO clause)
+ - CREATE PROCEDURE ... BEGIN DROP EVENT ... END|
+ */
+ if (lex->sphead)
+ my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
+
+ if (!lex->make_sp_head(thd, lex->event_parse_data->identifier,
+ TYPE_ENUM_PROCEDURE))
+ MYSQL_YYABORT;
+
+ lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
+ }
+ sp_proc_stmt
+ {
+ LEX *lex= thd->lex;
+
+ /* return back to the original memory root ASAP */
+ lex->sphead->set_stmt_end(thd);
+ lex->sphead->restore_thd_mem_root(thd);
+
+ lex->event_parse_data->body_changed= TRUE;
+ }
+ ;
+
+clear_privileges:
+ /* Nothing */
+ {
+ LEX *lex=Lex;
+ lex->users_list.empty();
+ lex->columns.empty();
+ lex->grant= lex->grant_tot_col= 0;
+ lex->all_privileges= 0;
+ lex->select_lex.db= 0;
+ lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
+ lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
+ bzero((char *)&(lex->mqh),sizeof(lex->mqh));
+ }
+ ;
+
+sp_name:
+ ident '.' ident
+ {
+ if (!($$= Lex->make_sp_name(thd, &$1, &$3)))
+ MYSQL_YYABORT;
+ }
+ | ident
+ {
+ if (!($$= Lex->make_sp_name(thd, &$1)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_sp_name:
+ /* Empty */ { $$= NULL; }
+ | sp_name { $$= $1; }
+ ;
+
+sp_a_chistics:
+ /* Empty */ {}
+ | sp_a_chistics sp_chistic {}
+ ;
+
+sp_c_chistics:
+ /* Empty */ {}
+ | sp_c_chistics sp_c_chistic {}
+ ;
+
+/* Characteristics for both create and alter */
+sp_chistic:
+ COMMENT_SYM TEXT_STRING_sys
+ { Lex->sp_chistics.comment= $2; }
+ | LANGUAGE_SYM SQL_SYM
+ { /* Just parse it, we only have one language for now. */ }
+ | NO_SYM SQL_SYM
+ { Lex->sp_chistics.daccess= SP_NO_SQL; }
+ | CONTAINS_SYM SQL_SYM
+ { Lex->sp_chistics.daccess= SP_CONTAINS_SQL; }
+ | READS_SYM SQL_SYM DATA_SYM
+ { Lex->sp_chistics.daccess= SP_READS_SQL_DATA; }
+ | MODIFIES_SYM SQL_SYM DATA_SYM
+ { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; }
+ | sp_suid
+ {}
+ ;
+
+/* Create characteristics */
+sp_c_chistic:
+ sp_chistic { }
+ | opt_not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= ! $1; }
+ ;
+
+sp_suid:
+ SQL_SYM SECURITY_SYM DEFINER_SYM
+ {
+ Lex->sp_chistics.suid= SP_IS_SUID;
+ }
+ | SQL_SYM SECURITY_SYM INVOKER_SYM
+ {
+ Lex->sp_chistics.suid= SP_IS_NOT_SUID;
+ }
+ ;
+
+call:
+ CALL_SYM sp_name
+ {
+ LEX *lex = Lex;
+
+ lex->sql_command= SQLCOM_CALL;
+ lex->spname= $2;
+ lex->value_list.empty();
+ sp_add_used_routine(lex, thd, $2, TYPE_ENUM_PROCEDURE);
+ }
+ opt_sp_cparam_list {}
+ ;
+
+/* CALL parameters */
+opt_sp_cparam_list:
+ /* Empty */
+ | '(' opt_sp_cparams ')'
+ ;
+
+opt_sp_cparams:
+ /* Empty */
+ | sp_cparams
+ ;
+
+sp_cparams:
+ sp_cparams ',' expr
+ {
+ Lex->value_list.push_back($3, thd->mem_root);
+ }
+ | expr
+ {
+ Lex->value_list.push_back($1, thd->mem_root);
+ }
+ ;
+
+/* Stored FUNCTION parameter declaration list */
+sp_fdparam_list:
+ /* Empty */
+ | sp_fdparams
+ ;
+
+sp_fdparams:
+ sp_fdparams ',' sp_param_name_and_type
+ | sp_param_name_and_type
+ ;
+
+sp_param_name:
+ ident
+ {
+ if (!($$= Lex->sp_param_init(&$1)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_param_name_and_type:
+ sp_param_name sp_param_type_with_opt_collate
+ {
+ if (Lex->sp_param_fill_definition($$= $1))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name qualified_column_ident '%' TYPE_SYM
+ {
+ Lex->sphead->fill_spvar_using_type_reference($$= $1, $2);
+ }
+ | sp_param_name ROW_SYM row_type_body
+ {
+ $$= $1;
+ $$->field_def.field_name= $$->name;
+ Lex->sphead->fill_spvar_definition(thd, &$$->field_def);
+ Lex->sphead->row_fill_field_definitions(thd, $3);
+ $$->field_def.set_row_field_definitions($3);
+ }
+ ;
+
+/* Stored PROCEDURE parameter declaration list */
+sp_pdparam_list:
+ /* Empty */
+ | sp_pdparams
+ ;
+
+sp_pdparams:
+ sp_pdparams ',' sp_pdparam
+ | sp_pdparam
+ ;
+
+sp_pdparam:
+ sp_param_name sp_opt_inout sp_param_type_with_opt_collate
+ {
+ $1->mode= $2;
+ if (Lex->sp_param_fill_definition($1))
+ MYSQL_YYABORT;
+ }
+ | sp_param_name sp_opt_inout qualified_column_ident '%' TYPE_SYM
+ {
+ Lex->sphead->fill_spvar_using_type_reference($1, $3);
+ }
+ | sp_param_name sp_opt_inout ROW_SYM row_type_body
+ {
+ $1->mode= $2;
+ $1->field_def.field_name= $1->name;
+ Lex->sphead->fill_spvar_definition(thd, &$1->field_def);
+ Lex->sphead->row_fill_field_definitions(thd, $4);
+ $1->field_def.set_row_field_definitions($4);
+ }
+ ;
+
+sp_opt_inout:
+ /* Empty */ { $$= sp_variable::MODE_IN; }
+ | IN_SYM { $$= sp_variable::MODE_IN; }
+ | OUT_SYM { $$= sp_variable::MODE_OUT; }
+ | INOUT_SYM { $$= sp_variable::MODE_INOUT; }
+ | IN_SYM OUT_SYM { $$= sp_variable::MODE_INOUT; }
+ ;
+
+sp_parenthesized_fdparam_list:
+ '('
+ {
+ Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start() + 1;
+ }
+ sp_fdparam_list
+ ')'
+ {
+ Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
+ }
+ ;
+
+sp_parenthesized_pdparam_list:
+ '('
+ {
+ Lex->sphead->m_param_begin= YYLIP->get_cpp_tok_start() + 1;
+ }
+ sp_pdparam_list
+ ')'
+ {
+ Lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
+ }
+ ;
+
+sp_no_param:
+ /* Empty */
+ {
+ Lex->sphead->m_param_begin= Lex->sphead->m_param_end=
+ YYLIP->get_cpp_tok_start() + 1;
+ }
+ ;
+
+opt_sp_parenthesized_fdparam_list:
+ sp_no_param
+ | sp_parenthesized_fdparam_list
+ ;
+
+opt_sp_parenthesized_pdparam_list:
+ sp_no_param
+ | sp_parenthesized_pdparam_list
+ ;
+
+sp_proc_stmts:
+ /* Empty */ {}
+ | sp_proc_stmts sp_proc_stmt ';'
+ ;
+
+sp_proc_stmts1:
+ sp_proc_stmt ';' {}
+ | sp_proc_stmts1 sp_proc_stmt ';'
+ ;
+
+sp_proc_stmts1_implicit_block:
+ {
+ Lex->sp_block_init(thd);
+ }
+ sp_proc_stmts1
+ {
+ if (Lex->sp_block_finalize(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_sp_decl_body_list:
+ /* Empty */
+ {
+ $$.init();
+ }
+ | sp_decl_body_list { $$= $1; }
+ ;
+
+sp_decl_body_list:
+ sp_decl_non_handler_list
+ {
+ if (Lex->sphead->sp_add_instr_cpush_for_cursors(thd, Lex->spcont))
+ MYSQL_YYABORT;
+ }
+ opt_sp_decl_handler_list
+ {
+ $$.join($1, $3);
+ }
+ | sp_decl_handler_list
+ ;
+
+sp_decl_non_handler_list:
+ sp_decl_non_handler ';' { $$= $1; }
+ | sp_decl_non_handler_list sp_decl_non_handler ';'
+ {
+ $$.join($1, $2);
+ }
+ ;
+
+sp_decl_handler_list:
+ sp_decl_handler ';' { $$= $1; }
+ | sp_decl_handler_list sp_decl_handler ';'
+ {
+ $$.join($1, $2);
+ }
+ ;
+
+opt_sp_decl_handler_list:
+ /* Empty*/ { $$.init(); }
+ | sp_decl_handler_list
+ ;
+
+qualified_column_ident:
+ sp_decl_ident '.' ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(&$1, &$3)))
+ MYSQL_YYABORT;
+ }
+ | sp_decl_ident '.' ident '.' ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(thd,
+ &$1, &$3, &$5)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+optionally_qualified_column_ident:
+ sp_decl_ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(&$1)))
+ MYSQL_YYABORT;
+ }
+ | sp_decl_ident '.' ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(&$1, &$3)))
+ MYSQL_YYABORT;
+ }
+ | sp_decl_ident '.' ident '.' ident
+ {
+ if (!($$= new (thd->mem_root) Qualified_column_ident(thd,
+ &$1, &$3, &$5)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+row_field_name:
+ ident_directly_assignable
+ {
+ if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
+ system_charset_info, 1))
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
+ if (!($$= new (thd->mem_root) Spvar_definition()))
+ MYSQL_YYABORT;
+ Lex->init_last_field($$, &$1, thd->variables.collation_database);
+ }
+ ;
+
+row_field_definition:
+ row_field_name type_with_opt_collate
+ ;
+
+row_field_definition_list:
+ row_field_definition
+ {
+ if (!($$= new (thd->mem_root) Row_definition_list()))
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | row_field_definition_list ',' row_field_definition
+ {
+ uint unused;
+ if ($1->find_row_field_by_name(&$3->field_name, &unused))
+ my_yyabort_error((ER_DUP_FIELDNAME, MYF(0), $3->field_name.str));
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+row_type_body:
+ '(' row_field_definition_list ')' { $$= $2; }
+ ;
+
+sp_decl_idents_init_vars:
+ sp_decl_idents
+ {
+ Lex->sp_variable_declarations_init(thd, $1);
+ }
+ ;
+
+sp_decl_non_handler:
+ sp_decl_idents_init_vars
+ type_with_opt_collate
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_finalize(thd, $1,
+ &Lex->last_field[0], $3))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ optionally_qualified_column_ident '%' TYPE_SYM
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $2, $5))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ optionally_qualified_column_ident '%' ROWTYPE_SYM
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $2, $5))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents_init_vars
+ ROW_SYM row_type_body
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
+ | ident_directly_assignable CONDITION_SYM FOR_SYM sp_cond
+ {
+ if (Lex->spcont->declare_condition(thd, &$1, $4))
+ MYSQL_YYABORT;
+ $$.vars= $$.hndlrs= $$.curs= 0;
+ $$.conds= 1;
+ }
+ | ident_directly_assignable EXCEPTION_SYM
+ {
+ sp_condition_value *spcond= new (thd->mem_root)
+ sp_condition_value_user_defined();
+ if (!spcond ||
+ Lex->spcont->declare_condition(thd, &$1, spcond))
+ MYSQL_YYABORT;
+ $$.vars= $$.hndlrs= $$.curs= 0;
+ $$.conds= 1;
+ }
+ | CURSOR_SYM ident_directly_assignable
+ {
+ Lex->sp_block_init(thd);
+ }
+ opt_parenthesized_cursor_formal_parameters
+ IS sp_cursor_stmt
+ {
+ sp_pcontext *param_ctx= Lex->spcont;
+ if (Lex->sp_block_finalize(thd))
+ MYSQL_YYABORT;
+ if (Lex->sp_declare_cursor(thd, &$2, $6, param_ctx, false))
+ MYSQL_YYABORT;
+ $$.vars= $$.conds= $$.hndlrs= 0;
+ $$.curs= 1;
+ }
+ ;
+
+sp_decl_handler:
+ sp_handler_type HANDLER_SYM FOR_SYM
+ {
+ if (Lex->sp_handler_declaration_init(thd, $1))
+ MYSQL_YYABORT;
+ }
+ sp_hcond_list sp_proc_stmt
+ {
+ if (Lex->sp_handler_declaration_finalize(thd, $1))
+ MYSQL_YYABORT;
+ $$.vars= $$.conds= $$.curs= 0;
+ $$.hndlrs= 1;
+ }
+ ;
+
+opt_parenthesized_cursor_formal_parameters:
+ /* Empty */
+ | '(' sp_fdparams ')'
+ ;
+
+
+sp_cursor_stmt_lex:
+ {
+ DBUG_ASSERT(thd->lex->sphead);
+ if (!($$= new (thd->mem_root) sp_lex_cursor(thd, thd->lex)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_cursor_stmt:
+ sp_cursor_stmt_lex
+ {
+ DBUG_ASSERT(thd->free_list == NULL);
+ Lex->sphead->reset_lex(thd, $1);
+ }
+ select
+ {
+ DBUG_ASSERT(Lex == $1);
+ if ($1->stmt_finalize(thd) ||
+ $1->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+sp_handler_type:
+ EXIT_SYM { $$= sp_handler::EXIT; }
+ | CONTINUE_SYM { $$= sp_handler::CONTINUE; }
+ /*| UNDO_SYM { QQ No yet } */
+ ;
+
+sp_hcond_list:
+ sp_hcond_element
+ { $$= 1; }
+ | sp_hcond_list ',' sp_hcond_element
+ { $$+= 1; }
+ ;
+
+sp_hcond_element:
+ sp_hcond
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont->parent_context();
+
+ if (ctx->check_duplicate_handler($1))
+ my_yyabort_error((ER_SP_DUP_HANDLER, MYF(0)));
+
+ sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
+ i->add_condition($1);
+ }
+ ;
+
+sp_cond:
+ ulong_num
+ { /* mysql errno */
+ if ($1 == 0)
+ my_yyabort_error((ER_WRONG_VALUE, MYF(0), "CONDITION", "0"));
+ $$= new (thd->mem_root) sp_condition_value($1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | sqlstate
+ ;
+
+sqlstate:
+ SQLSTATE_SYM opt_value TEXT_STRING_literal
+ { /* SQLSTATE */
+
+ /*
+ An error is triggered:
+ - if the specified string is not a valid SQLSTATE,
+ - or if it represents the completion condition -- it is not
+ allowed to SIGNAL, or declare a handler for the completion
+ condition.
+ */
+ if (!is_sqlstate_valid(&$3) || is_sqlstate_completion($3.str))
+ my_yyabort_error((ER_SP_BAD_SQLSTATE, MYF(0), $3.str));
+ $$= new (thd->mem_root) sp_condition_value($3.str);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_value:
+ /* Empty */ {}
+ | VALUE_SYM {}
+ ;
+
+sp_hcond:
+ sp_cond
+ {
+ $$= $1;
+ }
+ | ident /* CONDITION name */
+ {
+ $$= Lex->spcont->find_declared_or_predefined_condition(&$1);
+ if ($$ == NULL)
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
+ }
+ | SQLWARNING_SYM /* SQLSTATEs 01??? */
+ {
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::WARNING);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | not FOUND_SYM /* SQLSTATEs 02??? */
+ {
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::NOT_FOUND);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | OTHERS_SYM /* All other SQLSTATEs */
+ {
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::EXCEPTION);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+raise_stmt:
+ RAISE_SYM opt_set_signal_information
+ {
+ if (Lex->add_resignal_statement(thd, NULL))
+ MYSQL_YYABORT;
+ }
+ | RAISE_SYM signal_value opt_set_signal_information
+ {
+ if (Lex->add_signal_statement(thd, $2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+signal_stmt:
+ SIGNAL_SYM signal_value opt_set_signal_information
+ {
+ if (Lex->add_signal_statement(thd, $2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+signal_value:
+ ident
+ {
+ LEX *lex= Lex;
+ sp_condition_value *cond;
+
+ /* SIGNAL foo cannot be used outside of stored programs */
+ if (lex->spcont == NULL)
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
+ cond= lex->spcont->find_declared_or_predefined_condition(&$1);
+ if (cond == NULL)
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
+ if (!cond->has_sql_state())
+ my_yyabort_error((ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0)));
+ $$= cond;
+ }
+ | sqlstate
+ { $$= $1; }
+ ;
+
+opt_signal_value:
+ /* empty */
+ { $$= NULL; }
+ | signal_value
+ { $$= $1; }
+ ;
+
+opt_set_signal_information:
+ /* empty */
+ {
+ thd->m_parser_state->m_yacc.m_set_signal_info.clear();
+ }
+ | SET signal_information_item_list
+ ;
+
+signal_information_item_list:
+ signal_condition_information_item_name '=' signal_allowed_expr
+ {
+ Set_signal_information *info;
+ info= &thd->m_parser_state->m_yacc.m_set_signal_info;
+ int index= (int) $1;
+ info->clear();
+ info->m_item[index]= $3;
+ }
+ | signal_information_item_list ','
+ signal_condition_information_item_name '=' signal_allowed_expr
+ {
+ Set_signal_information *info;
+ info= &thd->m_parser_state->m_yacc.m_set_signal_info;
+ int index= (int) $3;
+ if (info->m_item[index] != NULL)
+ my_yyabort_error((ER_DUP_SIGNAL_SET, MYF(0),
+ Diag_condition_item_names[index].str));
+ info->m_item[index]= $5;
+ }
+ ;
+
+/*
+ Only a limited subset of <expr> are allowed in SIGNAL/RESIGNAL.
+*/
+signal_allowed_expr:
+ literal
+ { $$= $1; }
+ | variable
+ {
+ if ($1->type() == Item::FUNC_ITEM)
+ {
+ Item_func *item= (Item_func*) $1;
+ if (item->functype() == Item_func::SUSERVAR_FUNC)
+ {
+ /*
+ Don't allow the following syntax:
+ SIGNAL/RESIGNAL ...
+ SET <signal condition item name> = @foo := expr
+ */
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ $$= $1;
+ }
+ | simple_ident
+ { $$= $1; }
+ ;
+
+/* conditions that can be set in signal / resignal */
+signal_condition_information_item_name:
+ CLASS_ORIGIN_SYM
+ { $$= DIAG_CLASS_ORIGIN; }
+ | SUBCLASS_ORIGIN_SYM
+ { $$= DIAG_SUBCLASS_ORIGIN; }
+ | CONSTRAINT_CATALOG_SYM
+ { $$= DIAG_CONSTRAINT_CATALOG; }
+ | CONSTRAINT_SCHEMA_SYM
+ { $$= DIAG_CONSTRAINT_SCHEMA; }
+ | CONSTRAINT_NAME_SYM
+ { $$= DIAG_CONSTRAINT_NAME; }
+ | CATALOG_NAME_SYM
+ { $$= DIAG_CATALOG_NAME; }
+ | SCHEMA_NAME_SYM
+ { $$= DIAG_SCHEMA_NAME; }
+ | TABLE_NAME_SYM
+ { $$= DIAG_TABLE_NAME; }
+ | COLUMN_NAME_SYM
+ { $$= DIAG_COLUMN_NAME; }
+ | CURSOR_NAME_SYM
+ { $$= DIAG_CURSOR_NAME; }
+ | MESSAGE_TEXT_SYM
+ { $$= DIAG_MESSAGE_TEXT; }
+ | MYSQL_ERRNO_SYM
+ { $$= DIAG_MYSQL_ERRNO; }
+ ;
+
+resignal_stmt:
+ RESIGNAL_SYM opt_signal_value opt_set_signal_information
+ {
+ if (Lex->add_resignal_statement(thd, $2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+get_diagnostics:
+ GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
+ {
+ Diagnostics_information *info= $4;
+
+ info->set_which_da($2);
+
+ Lex->sql_command= SQLCOM_GET_DIAGNOSTICS;
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_get_diagnostics(info);
+
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+which_area:
+ /* If <which area> is not specified, then CURRENT is implicit. */
+ { $$= Diagnostics_information::CURRENT_AREA; }
+ | CURRENT_SYM
+ { $$= Diagnostics_information::CURRENT_AREA; }
+ ;
+
+diagnostics_information:
+ statement_information
+ {
+ $$= new (thd->mem_root) Statement_information($1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CONDITION_SYM condition_number condition_information
+ {
+ $$= new (thd->mem_root) Condition_information($2, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+statement_information:
+ statement_information_item
+ {
+ $$= new (thd->mem_root) List<Statement_information_item>;
+ if ($$ == NULL || $$->push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | statement_information ',' statement_information_item
+ {
+ if ($1->push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+statement_information_item:
+ simple_target_specification '=' statement_information_item_name
+ {
+ $$= new (thd->mem_root) Statement_information_item($3, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+
+simple_target_specification:
+ ident
+ {
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+ $$= thd->lex->create_item_for_sp_var(&$1, NULL,
+ lip->get_tok_start(),
+ lip->get_ptr());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '@' ident_or_text
+ {
+ $$= new (thd->mem_root) Item_func_get_user_var(thd, &$2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+statement_information_item_name:
+ NUMBER_SYM
+ { $$= Statement_information_item::NUMBER; }
+ | ROW_COUNT_SYM
+ { $$= Statement_information_item::ROW_COUNT; }
+ ;
+
+/*
+ Only a limited subset of <expr> are allowed in GET DIAGNOSTICS
+ <condition number>, same subset as for SIGNAL/RESIGNAL.
+*/
+condition_number:
+ signal_allowed_expr
+ { $$= $1; }
+ ;
+
+condition_information:
+ condition_information_item
+ {
+ $$= new (thd->mem_root) List<Condition_information_item>;
+ if ($$ == NULL || $$->push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | condition_information ',' condition_information_item
+ {
+ if ($1->push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+condition_information_item:
+ simple_target_specification '=' condition_information_item_name
+ {
+ $$= new (thd->mem_root) Condition_information_item($3, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+
+condition_information_item_name:
+ CLASS_ORIGIN_SYM
+ { $$= Condition_information_item::CLASS_ORIGIN; }
+ | SUBCLASS_ORIGIN_SYM
+ { $$= Condition_information_item::SUBCLASS_ORIGIN; }
+ | CONSTRAINT_CATALOG_SYM
+ { $$= Condition_information_item::CONSTRAINT_CATALOG; }
+ | CONSTRAINT_SCHEMA_SYM
+ { $$= Condition_information_item::CONSTRAINT_SCHEMA; }
+ | CONSTRAINT_NAME_SYM
+ { $$= Condition_information_item::CONSTRAINT_NAME; }
+ | CATALOG_NAME_SYM
+ { $$= Condition_information_item::CATALOG_NAME; }
+ | SCHEMA_NAME_SYM
+ { $$= Condition_information_item::SCHEMA_NAME; }
+ | TABLE_NAME_SYM
+ { $$= Condition_information_item::TABLE_NAME; }
+ | COLUMN_NAME_SYM
+ { $$= Condition_information_item::COLUMN_NAME; }
+ | CURSOR_NAME_SYM
+ { $$= Condition_information_item::CURSOR_NAME; }
+ | MESSAGE_TEXT_SYM
+ { $$= Condition_information_item::MESSAGE_TEXT; }
+ | MYSQL_ERRNO_SYM
+ { $$= Condition_information_item::MYSQL_ERRNO; }
+ | RETURNED_SQLSTATE_SYM
+ { $$= Condition_information_item::RETURNED_SQLSTATE; }
+ ;
+
+sp_decl_ident:
+ IDENT_sys
+ | sp_decl_ident_keyword
+ {
+ $$.str= thd->strmake($1.str, $1.length);
+ if ($$.str == NULL)
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ }
+ ;
+
+sp_decl_ident_keyword:
+ keyword_directly_assignable
+ | keyword_sp_not_data_type
+ ;
+
+
+sp_decl_idents:
+ sp_decl_ident
+ {
+ /* NOTE: field definition is filled in sp_decl section. */
+
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_variable(&$1, TRUE))
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $1.str));
+ spc->add_variable(thd, &$1);
+ $$= 1;
+ }
+ | sp_decl_idents ',' ident
+ {
+ /* NOTE: field definition is filled in sp_decl section. */
+
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+
+ if (spc->find_variable(&$3, TRUE))
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $3.str));
+ spc->add_variable(thd, &$3);
+ $$= $1 + 1;
+ }
+ ;
+
+sp_opt_default:
+ /* Empty */ { $$ = NULL; }
+ | DEFAULT expr { $$ = $2; }
+ | SET_VAR expr { $$ = $2; }
+ ;
+
+sp_proc_stmt:
+ sp_labeled_block
+ | sp_unlabeled_block
+ | sp_labeled_control
+ | sp_unlabeled_control
+ | sp_labelable_stmt
+ | labels_declaration_oracle sp_labelable_stmt {}
+ ;
+
+sp_labelable_stmt:
+ sp_proc_stmt_statement
+ | sp_proc_stmt_continue
+ | sp_proc_stmt_exit
+ | sp_proc_stmt_leave
+ | sp_proc_stmt_iterate
+ | sp_proc_stmt_goto
+ | sp_proc_stmt_open
+ | sp_proc_stmt_fetch
+ | sp_proc_stmt_close
+ | sp_proc_stmt_return
+ | sp_proc_stmt_if
+ | case_stmt_specification
+ | NULL_SYM { }
+ ;
+
+sp_proc_stmt_compound_ok:
+ sp_proc_stmt_if
+ | case_stmt_specification
+ | sp_unlabeled_block
+ | sp_unlabeled_control
+ ;
+
+sp_proc_stmt_if:
+ IF_SYM
+ {
+ if (Lex->maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->sphead->new_cont_backpatch(NULL);
+ }
+ sp_if END IF_SYM
+ { Lex->sphead->do_cont_backpatch(); }
+ ;
+
+sp_statement:
+ statement
+ | ident_directly_assignable
+ {
+ // Direct procedure call (without the CALL keyword)
+ LEX *lex = Lex;
+ if (!(lex->spname= lex->make_sp_name(thd, &$1)))
+ MYSQL_YYABORT;
+ lex->sql_command= SQLCOM_CALL;
+ lex->value_list.empty();
+ sp_add_used_routine(lex, thd, lex->spname, TYPE_ENUM_PROCEDURE);
+ }
+ opt_sp_cparam_list
+ | ident_directly_assignable '.' ident
+ {
+ LEX *lex = Lex;
+ if (!(lex->spname= lex->make_sp_name(thd, &$1, &$3)))
+ MYSQL_YYABORT;
+ lex->sql_command= SQLCOM_CALL;
+ lex->value_list.empty();
+ sp_add_used_routine(lex, thd, lex->spname, TYPE_ENUM_PROCEDURE);
+ }
+ opt_sp_cparam_list
+ ;
+
+sp_proc_stmt_statement:
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= YYLIP;
+
+ lex->sphead->reset_lex(thd);
+ lex->sphead->m_tmp_query= lip->get_tok_start();
+ }
+ sp_statement
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= YYLIP;
+ sp_head *sp= lex->sphead;
+
+ sp->m_flags|= sp_get_flags_for_command(lex);
+ /* "USE db" doesn't work in a procedure */
+ if (lex->sql_command == SQLCOM_CHANGE_DB)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE"));
+ /*
+ Don't add an instruction for SET statements, since all
+ instructions for them were already added during processing
+ of "set" rule.
+ */
+ DBUG_ASSERT(lex->sql_command != SQLCOM_SET_OPTION ||
+ lex->var_list.is_empty());
+ if (lex->sql_command != SQLCOM_SET_OPTION)
+ {
+ sp_instr_stmt *i=new (thd->mem_root)
+ sp_instr_stmt(sp->instructions(), lex->spcont, lex);
+ if (i == NULL)
+ MYSQL_YYABORT;
+
+ /*
+ Extract the query statement from the tokenizer. The
+ end is either lex->ptr, if there was no lookahead,
+ lex->tok_end otherwise.
+ */
+ if (yychar == YYEMPTY)
+ i->m_query.length= lip->get_ptr() - sp->m_tmp_query;
+ else
+ i->m_query.length= lip->get_tok_start() - sp->m_tmp_query;;
+ if (!(i->m_query.str= strmake_root(thd->mem_root,
+ sp->m_tmp_query,
+ i->m_query.length)) ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
+ }
+ if (sp->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_return:
+ RETURN_SYM
+ { Lex->sphead->reset_lex(thd); }
+ expr
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ if (sp->m_type != TYPE_ENUM_FUNCTION)
+ my_yyabort_error((ER_SP_BADRETURN, MYF(0)));
+
+ sp_instr_freturn *i;
+
+ i= new (thd->mem_root)
+ sp_instr_freturn(sp->instructions(), lex->spcont, $3,
+ sp->m_return_field_def.type_handler(), lex);
+ if (i == NULL || sp->add_instr(i))
+ MYSQL_YYABORT;
+ sp->m_flags|= sp_head::HAS_RETURN;
+
+ if (sp->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ | RETURN_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+
+ if (sp->m_type != TYPE_ENUM_PROCEDURE)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ sp_instr_preturn *i;
+ i= new (thd->mem_root)
+ sp_instr_preturn(sp->instructions(), lex->spcont);
+ if (i == NULL || sp->add_instr(i))
+ MYSQL_YYABORT;
+ }
+ ;
+
+reset_lex_expr:
+ { Lex->sphead->reset_lex(thd); } expr { $$= $2; }
+ ;
+
+sp_proc_stmt_exit:
+ EXIT_SYM
+ {
+ if (Lex->sp_exit_statement(thd, NULL))
+ MYSQL_YYABORT;
+ }
+ | EXIT_SYM label_ident
+ {
+ if (Lex->sp_exit_statement(thd, &$2, NULL))
+ MYSQL_YYABORT;
+ }
+ | EXIT_SYM WHEN_SYM reset_lex_expr
+ {
+ if (Lex->sp_exit_statement(thd, $3) ||
+ Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ | EXIT_SYM label_ident WHEN_SYM reset_lex_expr
+ {
+ if (Lex->sp_exit_statement(thd, &$2, $4) ||
+ Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_continue:
+ CONTINUE_SYM
+ {
+ if (Lex->sp_continue_statement(thd, NULL))
+ MYSQL_YYABORT;
+ }
+ | CONTINUE_SYM label_ident
+ {
+ if (Lex->sp_continue_statement(thd, &$2, NULL))
+ MYSQL_YYABORT;
+ }
+ | CONTINUE_SYM WHEN_SYM reset_lex_expr
+ {
+ if (Lex->sp_continue_statement(thd, $3) ||
+ Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ | CONTINUE_SYM label_ident WHEN_SYM reset_lex_expr
+ {
+ if (Lex->sp_continue_statement(thd, &$2, $4) ||
+ Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+sp_proc_stmt_leave:
+ LEAVE_SYM label_ident
+ {
+ if (Lex->sp_leave_statement(thd, &$2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_iterate:
+ ITERATE_SYM label_ident
+ {
+ if (Lex->sp_iterate_statement(thd, &$2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_goto:
+ GOTO_SYM label_ident
+ {
+ if (Lex->sp_goto_statement(thd, &$2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+assignment_source_lex:
+ {
+ DBUG_ASSERT(Lex->sphead);
+ if (!($$= new (thd->mem_root) sp_assignment_lex(thd, thd->lex)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+assignment_source_expr:
+ assignment_source_lex
+ {
+ DBUG_ASSERT(thd->free_list == NULL);
+ Lex->sphead->reset_lex(thd, $1);
+ }
+ expr
+ {
+ DBUG_ASSERT($1 == thd->lex);
+ $$= $1;
+ $$->sp_lex_in_use= true;
+ $$->set_item_and_free_list($3, thd->free_list);
+ thd->free_list= NULL;
+ if ($$->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+for_loop_bound_expr:
+ assignment_source_lex
+ {
+ Lex->sphead->reset_lex(thd, $1);
+ }
+ expr
+ {
+ DBUG_ASSERT($1 == thd->lex);
+ $$= $1;
+ $$->sp_lex_in_use= true;
+ $$->set_item_and_free_list($3, NULL);
+ if ($$->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+cursor_actual_parameters:
+ assignment_source_expr
+ {
+ if (!($$= new (thd->mem_root) List<sp_assignment_lex>))
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | cursor_actual_parameters ',' assignment_source_expr
+ {
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+opt_parenthesized_cursor_actual_parameters:
+ /* Empty */ { $$= NULL; }
+ | '(' cursor_actual_parameters ')' { $$= $2; }
+ ;
+
+sp_proc_stmt_open:
+ OPEN_SYM ident opt_parenthesized_cursor_actual_parameters
+ {
+ if (Lex->sp_open_cursor(thd, &$2, $3))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_fetch_head:
+ FETCH_SYM ident INTO
+ {
+ if (Lex->sp_add_cfetch(thd, &$2))
+ MYSQL_YYABORT;
+ }
+ | FETCH_SYM FROM ident INTO
+ {
+ if (Lex->sp_add_cfetch(thd, &$3))
+ MYSQL_YYABORT;
+ }
+ | FETCH_SYM NEXT_SYM FROM ident INTO
+ {
+ if (Lex->sp_add_cfetch(thd, &$4))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_proc_stmt_fetch:
+ sp_proc_stmt_fetch_head sp_fetch_list { }
+ ;
+
+sp_proc_stmt_close:
+ CLOSE_SYM ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ uint offset;
+ sp_instr_cclose *i;
+
+ if (! lex->spcont->find_cursor(&$2, &offset, false))
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
+ sp_instr_cclose(sp->instructions(), lex->spcont, offset);
+ if (i == NULL ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_fetch_list:
+ ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *spc= lex->spcont;
+ sp_variable *spv;
+
+ if (!spc || !(spv = spc->find_variable(&$1, false)))
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
+
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
+ }
+ | sp_fetch_list ',' ident
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *spc= lex->spcont;
+ sp_variable *spv;
+
+ if (!spc || !(spv = spc->find_variable(&$3, false)))
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
+
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
+ }
+ ;
+
+sp_if:
+ { Lex->sphead->reset_lex(thd); }
+ expr THEN_SYM
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ uint ip= sp->instructions();
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(ip, ctx, $2, lex);
+ if (i == NULL ||
+ sp->push_backpatch(thd, i, ctx->push_label(thd, &empty_clex_str, 0)) ||
+ sp->add_cont_backpatch(i) ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
+ if (sp->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ sp_proc_stmts1_implicit_block
+ {
+ sp_head *sp= Lex->sphead;
+ sp_pcontext *ctx= Lex->spcont;
+ uint ip= sp->instructions();
+ sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(ip, ctx);
+ if (i == NULL ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
+ sp->backpatch(ctx->pop_label());
+ sp->push_backpatch(thd, i, ctx->push_label(thd, &empty_clex_str, 0));
+ }
+ sp_elseifs
+ {
+ LEX *lex= Lex;
+
+ lex->sphead->backpatch(lex->spcont->pop_label());
+ }
+ ;
+
+sp_elseifs:
+ /* Empty */
+ | ELSIF_SYM sp_if
+ | ELSE sp_proc_stmts1_implicit_block
+ ;
+
+case_stmt_specification:
+ CASE_SYM
+ {
+ if (Lex->maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+
+ /**
+ An example of the CASE statement in use is
+ <pre>
+ CREATE PROCEDURE proc_19194_simple(i int)
+ BEGIN
+ DECLARE str CHAR(10);
+
+ CASE i
+ WHEN 1 THEN SET str="1";
+ WHEN 2 THEN SET str="2";
+ WHEN 3 THEN SET str="3";
+ ELSE SET str="unknown";
+ END CASE;
+
+ SELECT str;
+ END
+ </pre>
+ The actions are used to generate the following code:
+ <pre>
+ SHOW PROCEDURE CODE proc_19194_simple;
+ Pos Instruction
+ 0 set str@1 NULL
+ 1 set_case_expr (12) 0 i@0
+ 2 jump_if_not 5(12) (case_expr@0 = 1)
+ 3 set str@1 _latin1'1'
+ 4 jump 12
+ 5 jump_if_not 8(12) (case_expr@0 = 2)
+ 6 set str@1 _latin1'2'
+ 7 jump 12
+ 8 jump_if_not 11(12) (case_expr@0 = 3)
+ 9 set str@1 _latin1'3'
+ 10 jump 12
+ 11 set str@1 _latin1'unknown'
+ 12 stmt 0 "SELECT str"
+ </pre>
+ */
+
+ Lex->sphead->new_cont_backpatch(NULL);
+
+ /*
+ BACKPATCH: Creating target label for the jump to after END CASE
+ (instruction 12 in the example)
+ */
+ Lex->spcont->push_label(thd, &empty_clex_str, Lex->sphead->instructions());
+ }
+ case_stmt_body
+ else_clause_opt
+ END
+ CASE_SYM
+ {
+ /*
+ BACKPATCH: Resolving forward jump from
+ "case_stmt_action_then" to after END CASE
+ (jump from instruction 4 to 12, 7 to 12 ... in the example)
+ */
+ Lex->sphead->backpatch(Lex->spcont->pop_label());
+
+ if ($3)
+ Lex->spcont->pop_case_expr_id();
+
+ Lex->sphead->do_cont_backpatch();
+ }
+ ;
+
+case_stmt_body:
+ { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
+ expr
+ {
+ if (Lex->case_stmt_action_expr($2))
+ MYSQL_YYABORT;
+
+ if (Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ simple_when_clause_list
+ { $$= 1; }
+ | searched_when_clause_list
+ { $$= 0; }
+ ;
+
+simple_when_clause_list:
+ simple_when_clause
+ | simple_when_clause_list simple_when_clause
+ ;
+
+searched_when_clause_list:
+ searched_when_clause
+ | searched_when_clause_list searched_when_clause
+ ;
+
+simple_when_clause:
+ WHEN_SYM
+ {
+ Lex->sphead->reset_lex(thd); /* For expr $3 */
+ }
+ expr
+ {
+ /* Simple case: <caseval> = <whenval> */
+
+ LEX *lex= Lex;
+ if (lex->case_stmt_action_when($3, true))
+ MYSQL_YYABORT;
+ /* For expr $3 */
+ if (lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ THEN_SYM
+ sp_proc_stmts1_implicit_block
+ {
+ if (Lex->case_stmt_action_then())
+ MYSQL_YYABORT;
+ }
+ ;
+
+searched_when_clause:
+ WHEN_SYM
+ {
+ Lex->sphead->reset_lex(thd); /* For expr $3 */
+ }
+ expr
+ {
+ LEX *lex= Lex;
+ if (lex->case_stmt_action_when($3, false))
+ MYSQL_YYABORT;
+ /* For expr $3 */
+ if (lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ THEN_SYM
+ sp_proc_stmts1_implicit_block
+ {
+ if (Lex->case_stmt_action_then())
+ MYSQL_YYABORT;
+ }
+ ;
+
+else_clause_opt:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ uint ip= sp->instructions();
+ sp_instr_error *i= new (thd->mem_root)
+ sp_instr_error(ip, lex->spcont, ER_SP_CASE_NOT_FOUND);
+ if (i == NULL ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
+ }
+ | ELSE sp_proc_stmts1_implicit_block
+ ;
+
+sp_opt_label:
+ /* Empty */ { $$= null_clex_str; }
+ | label_ident { $$= $1; }
+ ;
+
+sp_block_label:
+ labels_declaration_oracle
+ {
+ if (Lex->spcont->block_label_declare(&$1))
+ MYSQL_YYABORT;
+ $$= $1;
+ }
+ ;
+
+sp_labeled_block:
+ sp_block_label
+ BEGIN_SYM
+ {
+ Lex->sp_block_init(thd, &$1);
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
+ sp_block_statements_and_exceptions
+ END
+ sp_opt_label
+ {
+ if (Lex->sp_block_finalize(thd, Lex_spblock($4), &$6))
+ MYSQL_YYABORT;
+ }
+ | sp_block_label
+ DECLARE_SYM
+ {
+ Lex->sp_block_init(thd, &$1);
+ }
+ sp_decl_body_list
+ {
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
+ BEGIN_SYM
+ sp_block_statements_and_exceptions
+ END
+ sp_opt_label
+ {
+ $4.hndlrs+= $7.hndlrs;
+ if (Lex->sp_block_finalize(thd, $4, &$9))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_not_atomic:
+ /* Empty */
+ | not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
+ ;
+
+sp_unlabeled_block:
+ BEGIN_SYM opt_not_atomic
+ {
+ if (Lex->maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->sp_block_init(thd);
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
+ sp_block_statements_and_exceptions
+ END
+ {
+ if (Lex->sp_block_finalize(thd, Lex_spblock($4)))
+ MYSQL_YYABORT;
+ }
+ | DECLARE_SYM
+ {
+ if (Lex->maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->sp_block_init(thd);
+ }
+ sp_decl_body_list
+ {
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
+ BEGIN_SYM
+ sp_block_statements_and_exceptions
+ END
+ {
+ $3.hndlrs+= $6.hndlrs;
+ if (Lex->sp_block_finalize(thd, $3))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_instr_addr:
+ { $$= Lex->sphead->instructions(); }
+ ;
+
+sp_body:
+ {
+ Lex->sp_block_init(thd);
+ }
+ opt_sp_decl_body_list
+ {
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
+ BEGIN_SYM
+ sp_block_statements_and_exceptions
+ {
+ $2.hndlrs+= $5.hndlrs;
+ if (Lex->sp_block_finalize(thd, $2))
+ MYSQL_YYABORT;
+ }
+ END
+ ;
+
+sp_block_statements_and_exceptions:
+ sp_instr_addr
+ sp_proc_stmts
+ {
+ if (Lex->sp_block_with_exceptions_finalize_executable_section(thd,
+ $1))
+ MYSQL_YYABORT;
+ }
+ opt_exception_clause
+ {
+ if (Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4))
+ MYSQL_YYABORT;
+ $$.init($4);
+ }
+ ;
+
+opt_exception_clause:
+ /* Empty */ { $$= 0; }
+ | EXCEPTION_SYM exception_handlers { $$= $2; }
+ ;
+
+exception_handlers:
+ exception_handler { $$= 1; }
+ | exception_handlers exception_handler { $$= $1 + 1; }
+ ;
+
+exception_handler:
+ WHEN_SYM
+ {
+ if (Lex->sp_handler_declaration_init(thd, sp_handler::EXIT))
+ MYSQL_YYABORT;
+ }
+ sp_hcond_list
+ THEN_SYM
+ sp_proc_stmts1_implicit_block
+ {
+ if (Lex->sp_handler_declaration_finalize(thd, sp_handler::EXIT))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/* This adds one shift/reduce conflict */
+opt_sp_for_loop_direction:
+ /* Empty */ { $$= 1; }
+ | REVERSE_SYM { $$= -1; }
+ ;
+
+sp_for_loop_index_and_bounds:
+ ident_directly_assignable sp_for_loop_bounds
+ {
+ if (Lex->sp_for_loop_declarations(thd, &$$, &$1, $2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_for_loop_bounds:
+ IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
+ DOT_DOT_SYM for_loop_bound_expr
+ {
+ $$.m_direction= $2;
+ $$.m_index= $3;
+ $$.m_upper_bound= $5;
+ $$.m_implicit_cursor= false;
+ }
+ | IN_SYM opt_sp_for_loop_direction for_loop_bound_expr
+ {
+ $$.m_direction= $2;
+ $$.m_index= $3;
+ $$.m_upper_bound= NULL;
+ $$.m_implicit_cursor= false;
+ }
+ | IN_SYM opt_sp_for_loop_direction '(' sp_cursor_stmt ')'
+ {
+ Item *item;
+ DBUG_ASSERT(Lex->sphead);
+ LEX_CSTRING name= {STRING_WITH_LEN("[implicit_cursor]") };
+ if (Lex->sp_declare_cursor(thd, &name, $4, NULL, true))
+ MYSQL_YYABORT;
+ if (!($$.m_index= new (thd->mem_root) sp_assignment_lex(thd, thd->lex)))
+ MYSQL_YYABORT;
+ $$.m_index->sp_lex_in_use= true;
+ Lex->sphead->reset_lex(thd, $$.m_index);
+ if (!(item= new (thd->mem_root) Item_field(thd,
+ Lex->current_context(),
+ NullS, NullS, &name)))
+ MYSQL_YYABORT;
+ $$.m_index->set_item_and_free_list(item, NULL);
+ if (Lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ $$.m_direction= 1;
+ $$.m_upper_bound= NULL;
+ $$.m_implicit_cursor= true;
+ }
+ ;
+
+loop_body:
+ sp_proc_stmts1 END LOOP_SYM
+ {
+ LEX *lex= Lex;
+ uint ip= lex->sphead->instructions();
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump *i= new (thd->mem_root)
+ sp_instr_jump(ip, lex->spcont, lab->ip);
+ if (i == NULL ||
+ lex->sphead->add_instr(i))
+ MYSQL_YYABORT;
+ }
+ ;
+
+while_body:
+ expr LOOP_SYM
+ {
+ LEX *lex= Lex;
+ if (lex->sp_while_loop_expression(thd, $1))
+ MYSQL_YYABORT;
+ if (lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ sp_proc_stmts1 END LOOP_SYM
+ {
+ if (Lex->sp_while_loop_finalize(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+repeat_body:
+ sp_proc_stmts1 UNTIL_SYM
+ { Lex->sphead->reset_lex(thd); }
+ expr END REPEAT_SYM
+ {
+ LEX *lex= Lex;
+ uint ip= lex->sphead->instructions();
+ sp_label *lab= lex->spcont->last_label(); /* Jumping back */
+ sp_instr_jump_if_not *i= new (thd->mem_root)
+ sp_instr_jump_if_not(ip, lex->spcont, $4, lab->ip, lex);
+ if (i == NULL ||
+ lex->sphead->add_instr(i))
+ MYSQL_YYABORT;
+ if (lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ /* We can shortcut the cont_backpatch here */
+ i->m_cont_dest= ip+1;
+ }
+ ;
+
+pop_sp_loop_label:
+ sp_opt_label
+ {
+ if (Lex->sp_pop_loop_label(thd, &$1))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sp_labeled_control:
+ labels_declaration_oracle LOOP_SYM
+ {
+ if (Lex->sp_push_loop_label(thd, &$1))
+ MYSQL_YYABORT;
+ }
+ loop_body pop_sp_loop_label
+ { }
+ | labels_declaration_oracle WHILE_SYM
+ {
+ if (Lex->sp_push_loop_label(thd, &$1))
+ MYSQL_YYABORT;
+ Lex->sphead->reset_lex(thd);
+ }
+ while_body pop_sp_loop_label
+ { }
+ | labels_declaration_oracle FOR_SYM
+ {
+ // See "The FOR LOOP statement" comments in sql_lex.cc
+ Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block
+ }
+ sp_for_loop_index_and_bounds
+ {
+ if (Lex->sp_push_loop_label(thd, &$1)) // The inner WHILE block
+ MYSQL_YYABORT;
+ if (Lex->sp_for_loop_condition_test(thd, $4))
+ MYSQL_YYABORT;
+ }
+ LOOP_SYM
+ sp_proc_stmts1
+ END LOOP_SYM
+ {
+ if (Lex->sp_for_loop_finalize(thd, $4))
+ MYSQL_YYABORT;
+ }
+ pop_sp_loop_label // The inner WHILE block
+ {
+ Lex_spblock tmp;
+ tmp.curs= MY_TEST($4.m_implicit_cursor);
+ if (Lex->sp_block_finalize(thd, tmp)) // The outer DECLARE..BEGIN..END
+ MYSQL_YYABORT;
+ }
+ | labels_declaration_oracle REPEAT_SYM
+ {
+ if (Lex->sp_push_loop_label(thd, &$1))
+ MYSQL_YYABORT;
+ }
+ repeat_body pop_sp_loop_label
+ { }
+ ;
+
+sp_unlabeled_control:
+ LOOP_SYM
+ {
+ if (Lex->sp_push_loop_empty_label(thd))
+ MYSQL_YYABORT;
+ }
+ loop_body
+ {
+ Lex->sp_pop_loop_empty_label(thd);
+ }
+ | WHILE_SYM
+ {
+ if (Lex->sp_push_loop_empty_label(thd))
+ MYSQL_YYABORT;
+ Lex->sphead->reset_lex(thd);
+ }
+ while_body
+ {
+ Lex->sp_pop_loop_empty_label(thd);
+ }
+ | FOR_SYM
+ {
+ // See "The FOR LOOP statement" comments in sql_lex.cc
+ if (Lex->maybe_start_compound_statement(thd))
+ MYSQL_YYABORT;
+ Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block
+ }
+ sp_for_loop_index_and_bounds
+ {
+ if (Lex->sp_push_loop_empty_label(thd)) // The inner WHILE block
+ MYSQL_YYABORT;
+ if (Lex->sp_for_loop_condition_test(thd, $3))
+ MYSQL_YYABORT;
+ }
+ LOOP_SYM
+ sp_proc_stmts1
+ END LOOP_SYM
+ {
+ Lex_spblock tmp;
+ tmp.curs= MY_TEST($3.m_implicit_cursor);
+ if (Lex->sp_for_loop_finalize(thd, $3))
+ MYSQL_YYABORT;
+ Lex->sp_pop_loop_empty_label(thd); // The inner WHILE block
+ if (Lex->sp_block_finalize(thd, tmp)) // The outer DECLARE..BEGIN..END
+ MYSQL_YYABORT;
+ }
+ | REPEAT_SYM
+ {
+ if (Lex->sp_push_loop_empty_label(thd))
+ MYSQL_YYABORT;
+ }
+ repeat_body
+ {
+ Lex->sp_pop_loop_empty_label(thd);
+ }
+ ;
+
+trg_action_time:
+ BEFORE_SYM
+ { Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; }
+ | AFTER_SYM
+ { Lex->trg_chistics.action_time= TRG_ACTION_AFTER; }
+ ;
+
+trg_event:
+ INSERT
+ { Lex->trg_chistics.event= TRG_EVENT_INSERT; }
+ | UPDATE_SYM
+ { Lex->trg_chistics.event= TRG_EVENT_UPDATE; }
+ | DELETE_SYM
+ { Lex->trg_chistics.event= TRG_EVENT_DELETE; }
+ ;
+/*
+ This part of the parser contains common code for all TABLESPACE
+ commands.
+ CREATE TABLESPACE name ...
+ ALTER TABLESPACE name CHANGE DATAFILE ...
+ ALTER TABLESPACE name ADD DATAFILE ...
+ ALTER TABLESPACE name access_mode
+ CREATE LOGFILE GROUP_SYM name ...
+ ALTER LOGFILE GROUP_SYM name ADD UNDOFILE ..
+ ALTER LOGFILE GROUP_SYM name ADD REDOFILE ..
+ DROP TABLESPACE name
+ DROP LOGFILE GROUP_SYM name
+*/
+change_tablespace_access:
+ tablespace_name
+ ts_access_mode
+ ;
+
+change_tablespace_info:
+ tablespace_name
+ CHANGE ts_datafile
+ change_ts_option_list
+ ;
+
+tablespace_info:
+ tablespace_name
+ ADD ts_datafile
+ opt_logfile_group_name
+ tablespace_option_list
+ ;
+
+opt_logfile_group_name:
+ /* empty */ {}
+ | USE_SYM LOGFILE_SYM GROUP_SYM ident
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->logfile_group_name= $4.str;
+ }
+ ;
+
+alter_tablespace_info:
+ tablespace_name
+ ADD ts_datafile
+ alter_tablespace_option_list
+ {
+ Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_ADD_FILE;
+ }
+ | tablespace_name
+ DROP ts_datafile
+ alter_tablespace_option_list
+ {
+ Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_DROP_FILE;
+ }
+ ;
+
+logfile_group_info:
+ logfile_group_name
+ add_log_file
+ logfile_group_option_list
+ ;
+
+alter_logfile_group_info:
+ logfile_group_name
+ add_log_file
+ alter_logfile_group_option_list
+ ;
+
+add_log_file:
+ ADD lg_undofile
+ | ADD lg_redofile
+ ;
+
+change_ts_option_list:
+ /* empty */ {}
+ change_ts_options
+ ;
+
+change_ts_options:
+ change_ts_option
+ | change_ts_options change_ts_option
+ | change_ts_options ',' change_ts_option
+ ;
+
+change_ts_option:
+ opt_ts_initial_size
+ | opt_ts_autoextend_size
+ | opt_ts_max_size
+ ;
+
+tablespace_option_list:
+ tablespace_options
+ ;
+
+tablespace_options:
+ tablespace_option
+ | tablespace_options tablespace_option
+ | tablespace_options ',' tablespace_option
+ ;
+
+tablespace_option:
+ opt_ts_initial_size
+ | opt_ts_autoextend_size
+ | opt_ts_max_size
+ | opt_ts_extent_size
+ | opt_ts_nodegroup
+ | opt_ts_engine
+ | ts_wait
+ | opt_ts_comment
+ ;
+
+alter_tablespace_option_list:
+ alter_tablespace_options
+ ;
+
+alter_tablespace_options:
+ alter_tablespace_option
+ | alter_tablespace_options alter_tablespace_option
+ | alter_tablespace_options ',' alter_tablespace_option
+ ;
+
+alter_tablespace_option:
+ opt_ts_initial_size
+ | opt_ts_autoextend_size
+ | opt_ts_max_size
+ | opt_ts_engine
+ | ts_wait
+ ;
+
+logfile_group_option_list:
+ logfile_group_options
+ ;
+
+logfile_group_options:
+ logfile_group_option
+ | logfile_group_options logfile_group_option
+ | logfile_group_options ',' logfile_group_option
+ ;
+
+logfile_group_option:
+ opt_ts_initial_size
+ | opt_ts_undo_buffer_size
+ | opt_ts_redo_buffer_size
+ | opt_ts_nodegroup
+ | opt_ts_engine
+ | ts_wait
+ | opt_ts_comment
+ ;
+
+alter_logfile_group_option_list:
+ alter_logfile_group_options
+ ;
+
+alter_logfile_group_options:
+ alter_logfile_group_option
+ | alter_logfile_group_options alter_logfile_group_option
+ | alter_logfile_group_options ',' alter_logfile_group_option
+ ;
+
+alter_logfile_group_option:
+ opt_ts_initial_size
+ | opt_ts_engine
+ | ts_wait
+ ;
+
+
+ts_datafile:
+ DATAFILE_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->data_file_name= $2.str;
+ }
+ ;
+
+lg_undofile:
+ UNDOFILE_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->undo_file_name= $2.str;
+ }
+ ;
+
+lg_redofile:
+ REDOFILE_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->redo_file_name= $2.str;
+ }
+ ;
+
+tablespace_name:
+ ident
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info= (new (thd->mem_root)
+ st_alter_tablespace());
+ if (lex->alter_tablespace_info == NULL)
+ MYSQL_YYABORT;
+ lex->alter_tablespace_info->tablespace_name= $1.str;
+ lex->sql_command= SQLCOM_ALTER_TABLESPACE;
+ }
+ ;
+
+logfile_group_name:
+ ident
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info= (new (thd->mem_root)
+ st_alter_tablespace());
+ if (lex->alter_tablespace_info == NULL)
+ MYSQL_YYABORT;
+ lex->alter_tablespace_info->logfile_group_name= $1.str;
+ lex->sql_command= SQLCOM_ALTER_TABLESPACE;
+ }
+ ;
+
+ts_access_mode:
+ READ_ONLY_SYM
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_access_mode= TS_READ_ONLY;
+ }
+ | READ_WRITE_SYM
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_access_mode= TS_READ_WRITE;
+ }
+ | NOT_SYM ACCESSIBLE_SYM
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_access_mode= TS_NOT_ACCESSIBLE;
+ }
+ ;
+
+opt_ts_initial_size:
+ INITIAL_SIZE_SYM opt_equal size_number
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->initial_size= $3;
+ }
+ ;
+
+opt_ts_autoextend_size:
+ AUTOEXTEND_SIZE_SYM opt_equal size_number
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->autoextend_size= $3;
+ }
+ ;
+
+opt_ts_max_size:
+ MAX_SIZE_SYM opt_equal size_number
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->max_size= $3;
+ }
+ ;
+
+opt_ts_extent_size:
+ EXTENT_SIZE_SYM opt_equal size_number
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->extent_size= $3;
+ }
+ ;
+
+opt_ts_undo_buffer_size:
+ UNDO_BUFFER_SIZE_SYM opt_equal size_number
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->undo_buffer_size= $3;
+ }
+ ;
+
+opt_ts_redo_buffer_size:
+ REDO_BUFFER_SIZE_SYM opt_equal size_number
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->redo_buffer_size= $3;
+ }
+ ;
+
+opt_ts_nodegroup:
+ NODEGROUP_SYM opt_equal real_ulong_num
+ {
+ LEX *lex= Lex;
+ if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP)
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP"));
+ lex->alter_tablespace_info->nodegroup_id= $3;
+ }
+ ;
+
+opt_ts_comment:
+ COMMENT_SYM opt_equal TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ if (lex->alter_tablespace_info->ts_comment != NULL)
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT"));
+ lex->alter_tablespace_info->ts_comment= $3.str;
+ }
+ ;
+
+opt_ts_engine:
+ opt_storage ENGINE_SYM opt_equal storage_engines
+ {
+ LEX *lex= Lex;
+ if (lex->alter_tablespace_info->storage_engine != NULL)
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE, MYF(0),
+ "STORAGE ENGINE"));
+ lex->alter_tablespace_info->storage_engine= $4;
+ }
+ ;
+
+opt_ts_wait:
+ /* empty */
+ | ts_wait
+ ;
+
+ts_wait:
+ WAIT_SYM
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->wait_until_completed= TRUE;
+ }
+ | NO_WAIT_SYM
+ {
+ LEX *lex= Lex;
+ if (!(lex->alter_tablespace_info->wait_until_completed))
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT"));
+ lex->alter_tablespace_info->wait_until_completed= FALSE;
+ }
+ ;
+
+size_number:
+ real_ulonglong_num { $$= $1;}
+ | IDENT_sys
+ {
+ ulonglong number;
+ uint text_shift_number= 0;
+ longlong prefix_number;
+ const char *start_ptr= $1.str;
+ uint str_len= $1.length;
+ const char *end_ptr= start_ptr + str_len;
+ int error;
+ prefix_number= my_strtoll10(start_ptr, (char**) &end_ptr, &error);
+ if ((start_ptr + str_len - 1) == end_ptr)
+ {
+ switch (end_ptr[0])
+ {
+ case 'g':
+ case 'G':
+ text_shift_number+=10;
+ /* fall through */
+ case 'm':
+ case 'M':
+ text_shift_number+=10;
+ /* fall through */
+ case 'k':
+ case 'K':
+ text_shift_number+=10;
+ break;
+ default:
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
+ }
+ if (prefix_number >> 31)
+ my_yyabort_error((ER_SIZE_OVERFLOW_ERROR, MYF(0)));
+ number= prefix_number << text_shift_number;
+ }
+ else
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
+ $$= number;
+ }
+ ;
+
+/*
+ End tablespace part
+*/
+
+create_body:
+ '(' create_field_list ')'
+ { Lex->create_info.option_list= NULL; }
+ opt_create_table_options opt_create_partitioning opt_create_select {}
+ | opt_create_table_options opt_create_partitioning opt_create_select {}
+ /*
+ the following rule is redundant, but there's a shift/reduce
+ conflict that prevents the rule above from parsing a syntax like
+ CREATE TABLE t1 (SELECT 1);
+ */
+ | '(' create_select_query_specification ')'
+ | '(' create_select_query_specification ')'
+ { Select->set_braces(1);} union_list {}
+ | '(' create_select_query_specification ')'
+ { Select->set_braces(1);} union_order_or_limit {}
+ | create_like
+ {
+
+ Lex->create_info.add(DDL_options_st::OPT_LIKE);
+ TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
+ $1, NULL, 0, TL_READ, MDL_SHARED_READ);
+ if (! src_table)
+ MYSQL_YYABORT;
+ /* CREATE TABLE ... LIKE is not allowed for views. */
+ src_table->required_type= TABLE_TYPE_NORMAL;
+ }
+ ;
+
+create_like:
+ LIKE table_ident { $$= $2; }
+ | '(' LIKE table_ident ')' { $$= $3; }
+ ;
+
+opt_create_select:
+ /* empty */ {}
+ | opt_duplicate opt_as create_select_query_expression
+ ;
+
+create_select_query_expression:
+ opt_with_clause SELECT_SYM create_select_part2 opt_table_expression
+ create_select_part4
+ {
+ Select->set_braces(0);
+ Select->set_with_clause($1);
+ }
+ union_clause
+ | opt_with_clause SELECT_SYM create_select_part2
+ create_select_part3_union_not_ready create_select_part4
+ {
+ Select->set_with_clause($1);
+ }
+ | '(' create_select_query_specification ')'
+ | '(' create_select_query_specification ')'
+ { Select->set_braces(1);} union_list {}
+ | '(' create_select_query_specification ')'
+ { Select->set_braces(1);} union_order_or_limit {}
+ ;
+
+opt_create_partitioning:
+ opt_partitioning
+ {
+ /*
+ Remove all tables used in PARTITION clause from the global table
+ list. Partitioning with subqueries is not allowed anyway.
+ */
+ TABLE_LIST *last_non_sel_table= Lex->create_last_non_select_table;
+ last_non_sel_table->next_global= 0;
+ Lex->query_tables_last= &last_non_sel_table->next_global;
+ }
+ ;
+
+/*
+ This part of the parser is about handling of the partition information.
+
+ It's first version was written by Mikael Ronstrm with lots of answers to
+ questions provided by Antony Curtis.
+
+ The partition grammar can be called from three places.
+ 1) CREATE TABLE ... PARTITION ..
+ 2) ALTER TABLE table_name PARTITION ...
+ 3) PARTITION ...
+
+ The first place is called when a new table is created from a MySQL client.
+ The second place is called when a table is altered with the ALTER TABLE
+ command from a MySQL client.
+ The third place is called when opening an frm file and finding partition
+ info in the .frm file. It is necessary to avoid allowing PARTITION to be
+ an allowed entry point for SQL client queries. This is arranged by setting
+ some state variables before arriving here.
+
+ To be able to handle errors we will only set error code in this code
+ and handle the error condition in the function calling the parser. This
+ is necessary to ensure we can also handle errors when calling the parser
+ from the openfrm function.
+*/
+opt_partitioning:
+ /* empty */ {}
+ | partitioning
+ ;
+
+partitioning:
+ PARTITION_SYM have_partitioning
+ {
+ LEX *lex= Lex;
+ lex->part_info= new (thd->mem_root) partition_info();
+ if (!lex->part_info)
+ {
+ mem_alloc_error(sizeof(partition_info));
+ MYSQL_YYABORT;
+ }
+ if (lex->sql_command == SQLCOM_ALTER_TABLE)
+ {
+ lex->alter_info.flags|= Alter_info::ALTER_PARTITION;
+ }
+ }
+ partition
+ ;
+
+have_partitioning:
+ /* empty */
+ {
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ LEX_CSTRING partition_name={STRING_WITH_LEN("partition")};
+ if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
+ my_yyabort_error((ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition"));
+#else
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), "partitioning",
+ "--with-plugin-partition"));
+#endif
+ }
+ ;
+
+partition_entry:
+ PARTITION_SYM
+ {
+ LEX *lex= Lex;
+ if (!lex->part_info)
+ {
+ thd->parse_error(ER_PARTITION_ENTRY_ERROR);
+ MYSQL_YYABORT;
+ }
+ /*
+ We enter here when opening the frm file to translate
+ partition info string into part_info data structure.
+ */
+ }
+ partition {}
+ ;
+
+partition:
+ BY
+ { Lex->safe_to_cache_query= 1; }
+ part_type_def opt_num_parts opt_sub_part part_defs
+ ;
+
+part_type_def:
+ opt_linear KEY_SYM opt_key_algo '(' part_field_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->list_of_part_fields= TRUE;
+ part_info->column_list= FALSE;
+ part_info->part_type= HASH_PARTITION;
+ }
+ | opt_linear HASH_SYM
+ { Lex->part_info->part_type= HASH_PARTITION; }
+ part_func {}
+ | RANGE_SYM part_func
+ { Lex->part_info->part_type= RANGE_PARTITION; }
+ | RANGE_SYM part_column_list
+ { Lex->part_info->part_type= RANGE_PARTITION; }
+ | LIST_SYM part_func
+ { Lex->part_info->part_type= LIST_PARTITION; }
+ | LIST_SYM part_column_list
+ { Lex->part_info->part_type= LIST_PARTITION; }
+ ;
+
+opt_linear:
+ /* empty */ {}
+ | LINEAR_SYM
+ { Lex->part_info->linear_hash_ind= TRUE;}
+ ;
+
+opt_key_algo:
+ /* empty */
+ { Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_NONE;}
+ | ALGORITHM_SYM '=' real_ulong_num
+ {
+ switch ($3) {
+ case 1:
+ Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_51;
+ break;
+ case 2:
+ Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_55;
+ break;
+ default:
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+part_field_list:
+ /* empty */ {}
+ | part_field_item_list {}
+ ;
+
+part_field_item_list:
+ part_field_item {}
+ | part_field_item_list ',' part_field_item {}
+ ;
+
+part_field_item:
+ ident
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->num_columns++;
+ if (part_info->part_field_list.push_back($1.str, thd->mem_root))
+ {
+ mem_alloc_error(1);
+ MYSQL_YYABORT;
+ }
+ if (part_info->num_columns > MAX_REF_PARTS)
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of partition fields"));
+ }
+ ;
+
+part_column_list:
+ COLUMNS '(' part_field_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->column_list= TRUE;
+ part_info->list_of_part_fields= TRUE;
+ }
+ ;
+
+
+part_func:
+ '(' remember_name part_func_expr remember_end ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->set_part_expr(thd, $2 + 1, $3, $4, FALSE))
+ { MYSQL_YYABORT; }
+ part_info->num_columns= 1;
+ part_info->column_list= FALSE;
+ }
+ ;
+
+sub_part_func:
+ '(' remember_name part_func_expr remember_end ')'
+ {
+ if (Lex->part_info->set_part_expr(thd, $2 + 1, $3, $4, TRUE))
+ { MYSQL_YYABORT; }
+ }
+ ;
+
+
+opt_num_parts:
+ /* empty */ {}
+ | PARTITIONS_SYM real_ulong_num
+ {
+ uint num_parts= $2;
+ partition_info *part_info= Lex->part_info;
+ if (num_parts == 0)
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "partitions"));
+
+ part_info->num_parts= num_parts;
+ part_info->use_default_num_partitions= FALSE;
+ }
+ ;
+
+opt_sub_part:
+ /* empty */ {}
+ | SUBPARTITION_SYM BY opt_linear HASH_SYM sub_part_func
+ { Lex->part_info->subpart_type= HASH_PARTITION; }
+ opt_num_subparts {}
+ | SUBPARTITION_SYM BY opt_linear KEY_SYM opt_key_algo
+ '(' sub_part_field_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->subpart_type= HASH_PARTITION;
+ part_info->list_of_subpart_fields= TRUE;
+ }
+ opt_num_subparts {}
+ ;
+
+sub_part_field_list:
+ sub_part_field_item {}
+ | sub_part_field_list ',' sub_part_field_item {}
+ ;
+
+sub_part_field_item:
+ ident
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->subpart_field_list.push_back($1.str, thd->mem_root))
+ {
+ mem_alloc_error(1);
+ MYSQL_YYABORT;
+ }
+ if (part_info->subpart_field_list.elements > MAX_REF_PARTS)
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of subpartition fields"));
+ }
+ ;
+
+part_func_expr:
+ bit_expr
+ {
+ if (!Lex->safe_to_cache_query)
+ {
+ thd->parse_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
+ MYSQL_YYABORT;
+ }
+ $$=$1;
+ }
+ ;
+
+opt_num_subparts:
+ /* empty */ {}
+ | SUBPARTITIONS_SYM real_ulong_num
+ {
+ uint num_parts= $2;
+ LEX *lex= Lex;
+ if (num_parts == 0)
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "subpartitions"));
+ lex->part_info->num_subparts= num_parts;
+ lex->part_info->use_default_num_subpartitions= FALSE;
+ }
+ ;
+
+part_defs:
+ /* empty */
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->part_type == RANGE_PARTITION)
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "RANGE"));
+ if (part_info->part_type == LIST_PARTITION)
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "LIST"));
+ }
+ | '(' part_def_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ uint count_curr_parts= part_info->partitions.elements;
+ if (part_info->num_parts != 0)
+ {
+ if (part_info->num_parts !=
+ count_curr_parts)
+ {
+ thd->parse_error(ER_PARTITION_WRONG_NO_PART_ERROR);
+ MYSQL_YYABORT;
+ }
+ }
+ else if (count_curr_parts > 0)
+ {
+ part_info->num_parts= count_curr_parts;
+ }
+ part_info->count_curr_subparts= 0;
+ }
+ ;
+
+part_def_list:
+ part_definition {}
+ | part_def_list ',' part_definition {}
+ ;
+
+part_definition:
+ PARTITION_SYM
+ {
+ partition_info *part_info= Lex->part_info;
+ partition_element *p_elem= new (thd->mem_root) partition_element();
+
+ if (!p_elem ||
+ part_info->partitions.push_back(p_elem, thd->mem_root))
+ {
+ mem_alloc_error(sizeof(partition_element));
+ MYSQL_YYABORT;
+ }
+ p_elem->part_state= PART_NORMAL;
+ part_info->curr_part_elem= p_elem;
+ part_info->current_partition= p_elem;
+ part_info->use_default_partitions= FALSE;
+ part_info->use_default_num_partitions= FALSE;
+ }
+ part_name
+ opt_part_values
+ opt_part_options
+ opt_sub_partition
+ {}
+ ;
+
+part_name:
+ ident
+ {
+ partition_info *part_info= Lex->part_info;
+ partition_element *p_elem= part_info->curr_part_elem;
+ if (check_ident_length(&$1))
+ MYSQL_YYABORT;
+ p_elem->partition_name= $1.str;
+ }
+ ;
+
+opt_part_values:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ if (! lex->is_partition_management())
+ {
+ if (part_info->part_type == RANGE_PARTITION)
+ my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
+ if (part_info->part_type == LIST_PARTITION)
+ my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
+ }
+ else
+ part_info->part_type= HASH_PARTITION;
+ }
+ | VALUES LESS_SYM THAN_SYM
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ if (! lex->is_partition_management())
+ {
+ if (part_info->part_type != RANGE_PARTITION)
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
+ }
+ else
+ part_info->part_type= RANGE_PARTITION;
+ }
+ part_func_max {}
+ | VALUES IN_SYM
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ if (! lex->is_partition_management())
+ {
+ if (part_info->part_type != LIST_PARTITION)
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
+ }
+ else
+ part_info->part_type= LIST_PARTITION;
+ }
+ part_values_in {}
+ | DEFAULT
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ if (! lex->is_partition_management())
+ {
+ if (part_info->part_type != LIST_PARTITION)
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "DEFAULT"));
+ }
+ else
+ part_info->part_type= LIST_PARTITION;
+ if (part_info->init_column_part(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ if (part_info->add_max_value(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+part_func_max:
+ MAXVALUE_SYM
+ {
+ partition_info *part_info= Lex->part_info;
+
+ if (part_info->num_columns &&
+ part_info->num_columns != 1U)
+ {
+ part_info->print_debug("Kilroy II", NULL);
+ thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
+ MYSQL_YYABORT;
+ }
+ else
+ part_info->num_columns= 1U;
+ if (part_info->init_column_part(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ if (part_info->add_max_value(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ | part_value_item {}
+ ;
+
+part_values_in:
+ part_value_item
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ part_info->print_debug("part_values_in: part_value_item", NULL);
+
+ if (part_info->num_columns != 1U)
+ {
+ if (!lex->is_partition_management() ||
+ part_info->num_columns == 0 ||
+ part_info->num_columns > MAX_REF_PARTS)
+ {
+ part_info->print_debug("Kilroy III", NULL);
+ thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
+ MYSQL_YYABORT;
+ }
+ /*
+ Reorganize the current large array into a list of small
+ arrays with one entry in each array. This can happen
+ in the first partition of an ALTER TABLE statement where
+ we ADD or REORGANIZE partitions. Also can only happen
+ for LIST partitions.
+ */
+ if (part_info->reorganize_into_single_field_col_val(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ }
+ | '(' part_value_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->num_columns < 2U)
+ {
+ thd->parse_error(ER_ROW_SINGLE_PARTITION_FIELD_ERROR);
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+part_value_list:
+ part_value_item {}
+ | part_value_list ',' part_value_item {}
+ ;
+
+part_value_item:
+ '('
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->print_debug("( part_value_item", NULL);
+ /* Initialisation code needed for each list of value expressions */
+ if (!(part_info->part_type == LIST_PARTITION &&
+ part_info->num_columns == 1U) &&
+ part_info->init_column_part(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ part_value_item_list {}
+ ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->print_debug(") part_value_item", NULL);
+ if (part_info->num_columns == 0)
+ part_info->num_columns= part_info->curr_list_object;
+ if (part_info->num_columns != part_info->curr_list_object)
+ {
+ /*
+ All value items lists must be of equal length, in some cases
+ which is covered by the above if-statement we don't know yet
+ how many columns is in the partition so the assignment above
+ ensures that we only report errors when we know we have an
+ error.
+ */
+ part_info->print_debug("Kilroy I", NULL);
+ thd->parse_error(ER_PARTITION_COLUMN_LIST_ERROR);
+ MYSQL_YYABORT;
+ }
+ part_info->curr_list_object= 0;
+ }
+ ;
+
+part_value_item_list:
+ part_value_expr_item {}
+ | part_value_item_list ',' part_value_expr_item {}
+ ;
+
+part_value_expr_item:
+ MAXVALUE_SYM
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->part_type == LIST_PARTITION)
+ {
+ thd->parse_error(ER_MAXVALUE_IN_VALUES_IN);
+ MYSQL_YYABORT;
+ }
+ if (part_info->add_max_value(thd))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ | bit_expr
+ {
+ LEX *lex= Lex;
+ partition_info *part_info= lex->part_info;
+ Item *part_expr= $1;
+
+ if (!lex->safe_to_cache_query)
+ {
+ thd->parse_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR);
+ MYSQL_YYABORT;
+ }
+ if (part_info->add_column_list_value(thd, part_expr))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+
+opt_sub_partition:
+ /* empty */
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->num_subparts != 0 &&
+ !part_info->use_default_subpartitions)
+ {
+ /*
+ We come here when we have defined subpartitions on the first
+ partition but not on all the subsequent partitions.
+ */
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ MYSQL_YYABORT;
+ }
+ }
+ | '(' sub_part_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ if (part_info->num_subparts != 0)
+ {
+ if (part_info->num_subparts !=
+ part_info->count_curr_subparts)
+ {
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ MYSQL_YYABORT;
+ }
+ }
+ else if (part_info->count_curr_subparts > 0)
+ {
+ if (part_info->partitions.elements > 1)
+ {
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ MYSQL_YYABORT;
+ }
+ part_info->num_subparts= part_info->count_curr_subparts;
+ }
+ part_info->count_curr_subparts= 0;
+ }
+ ;
+
+sub_part_list:
+ sub_part_definition {}
+ | sub_part_list ',' sub_part_definition {}
+ ;
+
+sub_part_definition:
+ SUBPARTITION_SYM
+ {
+ partition_info *part_info= Lex->part_info;
+ partition_element *curr_part= part_info->current_partition;
+ partition_element *sub_p_elem= new (thd->mem_root)
+ partition_element(curr_part);
+ if (part_info->use_default_subpartitions &&
+ part_info->partitions.elements >= 2)
+ {
+ /*
+ create table t1 (a int)
+ partition by list (a) subpartition by hash (a)
+ (partition p0 values in (1),
+ partition p1 values in (2) subpartition sp11);
+ causes use to arrive since we are on the second
+ partition, but still use_default_subpartitions
+ is set. When we come here we're processing at least
+ the second partition (the current partition processed
+ have already been put into the partitions list.
+ */
+ thd->parse_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR);
+ MYSQL_YYABORT;
+ }
+ if (!sub_p_elem ||
+ curr_part->subpartitions.push_back(sub_p_elem, thd->mem_root))
+ {
+ mem_alloc_error(sizeof(partition_element));
+ MYSQL_YYABORT;
+ }
+ part_info->curr_part_elem= sub_p_elem;
+ part_info->use_default_subpartitions= FALSE;
+ part_info->use_default_num_subpartitions= FALSE;
+ part_info->count_curr_subparts++;
+ }
+ sub_name opt_part_options {}
+ ;
+
+sub_name:
+ ident_or_text
+ {
+ if (check_ident_length(&$1))
+ MYSQL_YYABORT;
+ Lex->part_info->curr_part_elem->partition_name= $1.str;
+ }
+ ;
+
+opt_part_options:
+ /* empty */ {}
+ | opt_part_option_list {}
+ ;
+
+opt_part_option_list:
+ opt_part_option_list opt_part_option {}
+ | opt_part_option {}
+ ;
+
+opt_part_option:
+ TABLESPACE opt_equal ident_or_text
+ { Lex->part_info->curr_part_elem->tablespace_name= $3.str; }
+ | opt_storage ENGINE_SYM opt_equal storage_engines
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->curr_part_elem->engine_type= $4;
+ part_info->default_engine_type= $4;
+ }
+ | CONNECTION_SYM opt_equal TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->part_info->curr_part_elem->connect_string.str= $3.str;
+ lex->part_info->curr_part_elem->connect_string.length= $3.length;
+ }
+ | NODEGROUP_SYM opt_equal real_ulong_num
+ { Lex->part_info->curr_part_elem->nodegroup_id= (uint16) $3; }
+ | MAX_ROWS opt_equal real_ulonglong_num
+ { Lex->part_info->curr_part_elem->part_max_rows= (ha_rows) $3; }
+ | MIN_ROWS opt_equal real_ulonglong_num
+ { Lex->part_info->curr_part_elem->part_min_rows= (ha_rows) $3; }
+ | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
+ { Lex->part_info->curr_part_elem->data_file_name= $4.str; }
+ | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
+ { Lex->part_info->curr_part_elem->index_file_name= $4.str; }
+ | COMMENT_SYM opt_equal TEXT_STRING_sys
+ { Lex->part_info->curr_part_elem->part_comment= $3.str; }
+ ;
+
+/*
+ End of partition parser part
+*/
+
+create_select_query_specification:
+ opt_with_clause SELECT_SYM create_select_part2 create_select_part3
+ create_select_part4
+ {
+ Select->set_with_clause($1);
+ }
+ ;
+
+create_select_part2:
+ {
+ LEX *lex=Lex;
+ if (lex->sql_command == SQLCOM_INSERT)
+ lex->sql_command= SQLCOM_INSERT_SELECT;
+ else if (lex->sql_command == SQLCOM_REPLACE)
+ lex->sql_command= SQLCOM_REPLACE_SELECT;
+ /*
+ The following work only with the local list, the global list
+ is created correctly in this case
+ */
+ lex->current_select->table_list.save_and_clear(&lex->save_list);
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ ;
+
+create_select_part3:
+ opt_table_expression
+ | create_select_part3_union_not_ready
+ ;
+
+create_select_part3_union_not_ready:
+ table_expression order_or_limit
+ | order_or_limit
+ ;
+
+create_select_part4:
+ opt_select_lock_type
+ {
+ /*
+ The following work only with the local list, the global list
+ is created correctly in this case
+ */
+ Lex->current_select->table_list.push_front(&Lex->save_list);
+ }
+ ;
+
+opt_as:
+ /* empty */ {}
+ | AS {}
+ ;
+
+opt_create_database_options:
+ /* empty */ {}
+ | create_database_options {}
+ ;
+
+create_database_options:
+ create_database_option {}
+ | create_database_options create_database_option {}
+ ;
+
+create_database_option:
+ default_collation {}
+ | default_charset {}
+ ;
+
+opt_if_not_exists_table_element:
+ /* empty */
+ {
+ Lex->check_exists= FALSE;
+ }
+ | IF_SYM not EXISTS
+ {
+ Lex->check_exists= TRUE;
+ }
+ ;
+
+opt_if_not_exists:
+ /* empty */
+ {
+ $$.init();
+ }
+ | IF_SYM not EXISTS
+ {
+ $$.set(DDL_options_st::OPT_IF_NOT_EXISTS);
+ }
+ ;
+
+create_or_replace:
+ CREATE /* empty */
+ {
+ $$.init();
+ }
+ | CREATE OR_SYM REPLACE
+ {
+ $$.set(DDL_options_st::OPT_OR_REPLACE);
+ }
+ ;
+
+opt_create_table_options:
+ /* empty */
+ | create_table_options
+ ;
+
+create_table_options_space_separated:
+ create_table_option
+ | create_table_option create_table_options_space_separated
+ ;
+
+create_table_options:
+ create_table_option
+ | create_table_option create_table_options
+ | create_table_option ',' create_table_options
+ ;
+
+create_table_option:
+ ENGINE_SYM opt_equal storage_engines
+ {
+ Lex->create_info.db_type= $3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
+ }
+ | MAX_ROWS opt_equal ulonglong_num
+ {
+ Lex->create_info.max_rows= $3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;
+ }
+ | MIN_ROWS opt_equal ulonglong_num
+ {
+ Lex->create_info.min_rows= $3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;
+ }
+ | AVG_ROW_LENGTH opt_equal ulong_num
+ {
+ Lex->create_info.avg_row_length=$3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;
+ }
+ | PASSWORD_SYM opt_equal TEXT_STRING_sys
+ {
+ Lex->create_info.password=$3.str;
+ Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD;
+ }
+ | COMMENT_SYM opt_equal TEXT_STRING_sys
+ {
+ Lex->create_info.comment=$3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT;
+ }
+ | AUTO_INC opt_equal ulonglong_num
+ {
+ Lex->create_info.auto_increment_value=$3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;
+ }
+ | PACK_KEYS_SYM opt_equal ulong_num
+ {
+ switch($3) {
+ case 0:
+ Lex->create_info.table_options|= HA_OPTION_NO_PACK_KEYS;
+ break;
+ case 1:
+ Lex->create_info.table_options|= HA_OPTION_PACK_KEYS;
+ break;
+ default:
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
+ }
+ | PACK_KEYS_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.table_options&=
+ ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
+ Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
+ }
+ | STATS_AUTO_RECALC_SYM opt_equal ulong_num
+ {
+ switch($3) {
+ case 0:
+ Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_OFF;
+ break;
+ case 1:
+ Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_ON;
+ break;
+ default:
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
+ }
+ | STATS_AUTO_RECALC_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.stats_auto_recalc= HA_STATS_AUTO_RECALC_DEFAULT;
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_AUTO_RECALC;
+ }
+ | STATS_PERSISTENT_SYM opt_equal ulong_num
+ {
+ switch($3) {
+ case 0:
+ Lex->create_info.table_options|= HA_OPTION_NO_STATS_PERSISTENT;
+ break;
+ case 1:
+ Lex->create_info.table_options|= HA_OPTION_STATS_PERSISTENT;
+ break;
+ default:
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
+ }
+ | STATS_PERSISTENT_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.table_options&=
+ ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT);
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_PERSISTENT;
+ }
+ | STATS_SAMPLE_PAGES_SYM opt_equal ulong_num
+ {
+ /* From user point of view STATS_SAMPLE_PAGES can be specified as
+ STATS_SAMPLE_PAGES=N (where 0<N<=65535, it does not make sense to
+ scan 0 pages) or STATS_SAMPLE_PAGES=default. Internally we record
+ =default as 0. See create_frm() in sql/table.cc, we use only two
+ bytes for stats_sample_pages and this is why we do not allow
+ larger values. 65535 pages, 16kb each means to sample 1GB, which
+ is impractical. If at some point this needs to be extended, then
+ we can store the higher bits from stats_sample_pages in .frm too. */
+ if ($3 == 0 || $3 > 0xffff)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ Lex->create_info.stats_sample_pages=$3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES;
+ }
+ | STATS_SAMPLE_PAGES_SYM opt_equal DEFAULT
+ {
+ Lex->create_info.stats_sample_pages=0;
+ Lex->create_info.used_fields|= HA_CREATE_USED_STATS_SAMPLE_PAGES;
+ }
+ | CHECKSUM_SYM opt_equal ulong_num
+ {
+ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM;
+ Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM;
+ }
+ | TABLE_CHECKSUM_SYM opt_equal ulong_num
+ {
+ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM;
+ Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM;
+ }
+ | PAGE_CHECKSUM_SYM opt_equal choice
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_PAGE_CHECKSUM;
+ Lex->create_info.page_checksum= $3;
+ }
+ | DELAY_KEY_WRITE_SYM opt_equal ulong_num
+ {
+ Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE;
+ Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE;
+ }
+ | ROW_FORMAT_SYM opt_equal row_types
+ {
+ Lex->create_info.row_type= $3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT;
+ }
+ | UNION_SYM opt_equal
+ {
+ Lex->select_lex.table_list.save_and_clear(&Lex->save_list);
+ }
+ '(' opt_table_list ')'
+ {
+ /*
+ Move the union list to the merge_list and exclude its tables
+ from the global list.
+ */
+ LEX *lex=Lex;
+ lex->create_info.merge_list= lex->select_lex.table_list;
+ lex->select_lex.table_list= lex->save_list;
+ /*
+ When excluding union list from the global list we assume that
+ elements of the former immediately follow elements which represent
+ table being created/altered and parent tables.
+ */
+ TABLE_LIST *last_non_sel_table= lex->create_last_non_select_table;
+ DBUG_ASSERT(last_non_sel_table->next_global ==
+ lex->create_info.merge_list.first);
+ last_non_sel_table->next_global= 0;
+ Lex->query_tables_last= &last_non_sel_table->next_global;
+
+ lex->create_info.used_fields|= HA_CREATE_USED_UNION;
+ }
+ | default_charset
+ | default_collation
+ | INSERT_METHOD opt_equal merge_insert_types
+ {
+ Lex->create_info.merge_insert_method= $3;
+ Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;
+ }
+ | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
+ {
+ Lex->create_info.data_file_name= $4.str;
+ Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR;
+ }
+ | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
+ {
+ Lex->create_info.index_file_name= $4.str;
+ Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR;
+ }
+ | TABLESPACE ident
+ {Lex->create_info.tablespace= $2.str;}
+ | STORAGE_SYM DISK_SYM
+ {Lex->create_info.storage_media= HA_SM_DISK;}
+ | STORAGE_SYM MEMORY_SYM
+ {Lex->create_info.storage_media= HA_SM_MEMORY;}
+ | CONNECTION_SYM opt_equal TEXT_STRING_sys
+ {
+ Lex->create_info.connect_string.str= $3.str;
+ Lex->create_info.connect_string.length= $3.length;
+ Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION;
+ }
+ | KEY_BLOCK_SIZE opt_equal ulong_num
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE;
+ Lex->create_info.key_block_size= $3;
+ }
+ | TRANSACTIONAL_SYM opt_equal choice
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
+ Lex->create_info.transactional= $3;
+ }
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
+ new (thd->mem_root)
+ engine_option_value($1, $3, true, &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
+ new (thd->mem_root)
+ engine_option_value($1, $3, false, &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal real_ulonglong_num
+ {
+ new (thd->mem_root)
+ engine_option_value($1, $3, &Lex->create_info.option_list,
+ &Lex->option_list_last, thd->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (thd->mem_root)
+ engine_option_value($1, &Lex->create_info.option_list,
+ &Lex->option_list_last);
+ }
+ | SEQUENCE_SYM opt_equal choice
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
+ Lex->create_info.sequence= $3;
+ }
+ ;
+
+default_charset:
+ opt_default charset opt_equal charset_name_or_default
+ {
+ if (Lex->create_info.add_table_option_default_charset($4))
+ MYSQL_YYABORT;
+ }
+ ;
+
+default_collation:
+ opt_default COLLATE_SYM opt_equal collation_name_or_default
+ {
+ HA_CREATE_INFO *cinfo= &Lex->create_info;
+ if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
+ cinfo->default_table_charset && $4 &&
+ !($4= merge_charset_and_collation(cinfo->default_table_charset,
+ $4)))
+ {
+ MYSQL_YYABORT;
+ }
+
+ Lex->create_info.default_table_charset= $4;
+ Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
+ }
+ ;
+
+storage_engines:
+ ident_or_text
+ {
+ plugin_ref plugin= ha_resolve_by_name(thd, &$1,
+ thd->lex->create_info.tmp_table());
+
+ if (plugin)
+ $$= plugin_hton(plugin);
+ else
+ {
+ if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
+ $$= 0;
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_UNKNOWN_STORAGE_ENGINE,
+ ER_THD(thd, ER_UNKNOWN_STORAGE_ENGINE),
+ $1.str);
+ }
+ }
+ ;
+
+known_storage_engines:
+ ident_or_text
+ {
+ plugin_ref plugin;
+ if ((plugin= ha_resolve_by_name(thd, &$1, false)))
+ $$= plugin_hton(plugin);
+ else
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
+ }
+ ;
+
+row_types:
+ DEFAULT { $$= ROW_TYPE_DEFAULT; }
+ | FIXED_SYM { $$= ROW_TYPE_FIXED; }
+ | DYNAMIC_SYM { $$= ROW_TYPE_DYNAMIC; }
+ | COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; }
+ | REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; }
+ | COMPACT_SYM { $$= ROW_TYPE_COMPACT; }
+ | PAGE_SYM { $$= ROW_TYPE_PAGE; }
+ ;
+
+merge_insert_types:
+ NO_SYM { $$= MERGE_INSERT_DISABLED; }
+ | FIRST_SYM { $$= MERGE_INSERT_TO_FIRST; }
+ | LAST_SYM { $$= MERGE_INSERT_TO_LAST; }
+ ;
+
+udf_type:
+ STRING_SYM {$$ = (int) STRING_RESULT; }
+ | REAL {$$ = (int) REAL_RESULT; }
+ | DECIMAL_SYM {$$ = (int) DECIMAL_RESULT; }
+ | INT_SYM {$$ = (int) INT_RESULT; }
+ ;
+
+
+create_field_list:
+ field_list
+ {
+ Lex->create_last_non_select_table= Lex->last_table();
+ }
+ ;
+
+field_list:
+ field_list_item
+ | field_list ',' field_list_item
+ ;
+
+field_list_item:
+ column_def { }
+ | key_def
+ | constraint_def
+ ;
+
+column_def:
+ field_spec
+ { $$= $1; }
+ | field_spec references
+ { $$= $1; }
+ ;
+
+key_def:
+ key_or_index opt_if_not_exists opt_ident opt_USING_key_algorithm
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key(Key::MULTIPLE, &$3, $4, $2))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options { }
+ | key_or_index opt_if_not_exists ident TYPE_SYM btree_or_rtree
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key(Key::MULTIPLE, &$3, $5, $2))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options { }
+ | fulltext opt_key_or_index opt_if_not_exists opt_ident
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key($1, &$4, HA_KEY_ALG_UNDEF, $3))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' fulltext_key_options { }
+ | spatial opt_key_or_index opt_if_not_exists opt_ident
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key($1, &$4, HA_KEY_ALG_UNDEF, $3))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' spatial_key_options { }
+ | opt_constraint constraint_key_type
+ opt_if_not_exists opt_ident
+ opt_USING_key_algorithm
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key($2, $4.str ? &$4 : &$1, $5, $3))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options { }
+ | opt_constraint constraint_key_type opt_if_not_exists ident
+ TYPE_SYM btree_or_rtree
+ {
+ Lex->option_list= NULL;
+ if (Lex->add_key($2, $4.str ? &$4 : &$1, $6, $3))
+ MYSQL_YYABORT;
+ }
+ '(' key_list ')' normal_key_options { }
+ | opt_constraint FOREIGN KEY_SYM opt_if_not_exists opt_ident
+ {
+ if (Lex->check_add_key($4) ||
+ !(Lex->last_key= (new (thd->mem_root)
+ Key(Key::MULTIPLE, $1.str ? &$1 : &$5,
+ HA_KEY_ALG_UNDEF, true, $4))))
+ MYSQL_YYABORT;
+ Lex->option_list= NULL;
+ }
+ '(' key_list ')' references
+ {
+ LEX *lex=Lex;
+ Key *key= (new (thd->mem_root)
+ Foreign_key($5.str ? &$5 : &$1,
+ &lex->last_key->columns,
+ &$10->db,
+ &$10->table,
+ &lex->ref_list,
+ lex->fk_delete_opt,
+ lex->fk_update_opt,
+ lex->fk_match_option,
+ $4));
+ if (key == NULL)
+ MYSQL_YYABORT;
+ /*
+ handle_if_exists_options() expectes the two keys in this order:
+ the Foreign_key, followed by its auto-generated Key.
+ */
+ lex->alter_info.key_list.push_back(key, thd->mem_root);
+ lex->alter_info.key_list.push_back(Lex->last_key, thd->mem_root);
+ lex->option_list= NULL;
+
+ /* Only used for ALTER TABLE. Ignored otherwise. */
+ lex->alter_info.flags|= Alter_info::ADD_FOREIGN_KEY;
+ }
+ ;
+
+constraint_def:
+ opt_constraint check_constraint
+ {
+ Lex->add_constraint(&$1, $2, FALSE);
+ }
+ ;
+
+opt_check_constraint:
+ /* empty */ { $$= (Virtual_column_info*) 0; }
+ | check_constraint { $$= $1;}
+ ;
+
+check_constraint:
+ CHECK_SYM '(' expr ')'
+ {
+ Virtual_column_info *v=
+ add_virtual_expression(thd, $3);
+ if (!v)
+ {
+ MYSQL_YYABORT;
+ }
+ $$= v;
+ }
+ ;
+
+opt_constraint:
+ /* empty */ { $$= null_clex_str; }
+ | constraint { $$= $1; }
+ ;
+
+constraint:
+ CONSTRAINT opt_ident { $$=$2; }
+ ;
+
+field_spec:
+ field_ident
+ {
+ LEX *lex=Lex;
+ Create_field *f= new (thd->mem_root) Create_field();
+
+ if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
+ system_charset_info, 1))
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
+
+ if (!f)
+ MYSQL_YYABORT;
+
+ lex->init_last_field(f, &$1, NULL);
+ $<create_field>$= f;
+ }
+ field_type_or_serial opt_check_constraint
+ {
+ LEX *lex=Lex;
+ $$= $<create_field>2;
+
+ $$->check_constraint= $4;
+
+ if ($$->check(thd))
+ MYSQL_YYABORT;
+
+ lex->alter_info.create_list.push_back($$, thd->mem_root);
+
+ $$->create_if_not_exists= Lex->check_exists;
+ if ($$->flags & PRI_KEY_FLAG)
+ lex->add_key_to_list(&$1, Key::PRIMARY, lex->check_exists);
+ else if ($$->flags & UNIQUE_KEY_FLAG)
+ lex->add_key_to_list(&$1, Key::UNIQUE, lex->check_exists);
+ }
+ ;
+
+field_type_or_serial:
+ field_type { Lex->last_field->set_attributes($1, Lex->charset); }
+ field_def
+ | SERIAL_SYM
+ {
+ Lex->last_field->set_handler(&type_handler_longlong);
+ Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG
+ | UNSIGNED_FLAG | UNIQUE_KEY_FLAG;
+ }
+ opt_serial_attribute
+ ;
+
+opt_serial_attribute:
+ /* empty */ {}
+ | opt_serial_attribute_list {}
+ ;
+
+opt_serial_attribute_list:
+ opt_serial_attribute_list serial_attribute {}
+ | serial_attribute
+ ;
+
+
+field_def:
+ opt_attribute
+ | opt_generated_always AS virtual_column_func
+ {
+ Lex->last_field->vcol_info= $3;
+ Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps
+ }
+ vcol_opt_specifier vcol_opt_attribute
+ ;
+
+opt_generated_always:
+ /* empty */ {}
+ | GENERATED_SYM ALWAYS_SYM {}
+ ;
+
+vcol_opt_specifier:
+ /* empty */
+ {
+ Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
+ }
+ | VIRTUAL_SYM
+ {
+ Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
+ }
+ | PERSISTENT_SYM
+ {
+ Lex->last_field->vcol_info->set_stored_in_db_flag(TRUE);
+ }
+ | STORED_SYM
+ {
+ Lex->last_field->vcol_info->set_stored_in_db_flag(TRUE);
+ }
+ ;
+
+vcol_opt_attribute:
+ /* empty */ {}
+ | vcol_opt_attribute_list {}
+ ;
+
+vcol_opt_attribute_list:
+ vcol_opt_attribute_list vcol_attribute {}
+ | vcol_attribute
+ ;
+
+vcol_attribute:
+ UNIQUE_SYM
+ {
+ LEX *lex=Lex;
+ lex->last_field->flags|= UNIQUE_KEY_FLAG;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
+ }
+ | UNIQUE_SYM KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->last_field->flags|= UNIQUE_KEY_FLAG;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
+ }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
+ ;
+
+parse_vcol_expr:
+ PARSE_VCOL_EXPR_SYM
+ {
+ /*
+ "PARSE_VCOL_EXPR" can only be used by the SQL server
+ when reading a '*.frm' file.
+ Prevent the end user from invoking this command.
+ */
+ MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr);
+ }
+ expr
+ {
+ Virtual_column_info *v= add_virtual_expression(thd, $3);
+ if (!v)
+ MYSQL_YYABORT;
+ Lex->last_field->vcol_info= v;
+ }
+ ;
+
+parenthesized_expr:
+ subselect
+ {
+ $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | expr
+ | expr ',' expr_list
+ {
+ $3->push_front($1, thd->mem_root);
+ $$= new (thd->mem_root) Item_row(thd, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+virtual_column_func:
+ '(' parenthesized_expr ')'
+ {
+ Virtual_column_info *v=
+ add_virtual_expression(thd, $2);
+ if (!v)
+ {
+ MYSQL_YYABORT;
+ }
+ $$= v;
+ }
+ ;
+
+expr_or_literal: column_default_non_parenthesized_expr | signed_literal ;
+
+column_default_expr:
+ virtual_column_func
+ | expr_or_literal
+ {
+ if (!($$= add_virtual_expression(thd, $1)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+field_type:
+ field_type_numeric
+ | field_type_temporal
+ | field_type_string
+ | field_type_lob
+ | field_type_misc
+ ;
+
+
+sp_param_field_type:
+ field_type_numeric
+ | field_type_temporal
+ | sp_param_field_type_string
+ | field_type_lob
+ | field_type_misc
+ ;
+
+
+field_type_numeric:
+ int_type opt_field_length field_options { $$.set($1, $2); }
+ | real_type opt_precision field_options { $$.set($1, $2); }
+ | FLOAT_SYM float_options field_options
+ {
+ $$.set(&type_handler_float, $2);
+ if ($2.length() && !$2.dec())
+ {
+ int err;
+ ulonglong tmp_length= my_strtoll10($2.length(), NULL, &err);
+ if (err || tmp_length > PRECISION_FOR_DOUBLE)
+ my_yyabort_error((ER_WRONG_FIELD_SPEC, MYF(0),
+ Lex->last_field->field_name.str));
+ if (tmp_length > PRECISION_FOR_FLOAT)
+ $$.set(&type_handler_double);
+ else
+ $$.set(&type_handler_float);
+ }
+ }
+ | BIT_SYM opt_field_length_default_1
+ {
+ $$.set(&type_handler_bit, $2);
+ }
+ | BOOL_SYM
+ {
+ $$.set(&type_handler_tiny, "1");
+ }
+ | BOOLEAN_SYM
+ {
+ $$.set(&type_handler_tiny, "1");
+ }
+ | DECIMAL_SYM float_options field_options
+ { $$.set(&type_handler_newdecimal, $2);}
+ | NUMBER_SYM float_options field_options
+ {
+ if ($2.length() != 0)
+ $$.set(&type_handler_newdecimal, $2);
+ else
+ $$.set(&type_handler_double);
+ }
+ | NUMERIC_SYM float_options field_options
+ { $$.set(&type_handler_newdecimal, $2);}
+ | FIXED_SYM float_options field_options
+ { $$.set(&type_handler_newdecimal, $2);}
+ ;
+
+
+field_type_string:
+ char opt_field_length_default_1 opt_binary
+ {
+ $$.set(&type_handler_string, $2);
+ }
+ | nchar opt_field_length_default_1 opt_bin_mod
+ {
+ $$.set(&type_handler_string, $2);
+ bincmp_collation(national_charset_info, $3);
+ }
+ | BINARY opt_field_length_default_1
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_string, $2);
+ }
+ | varchar field_length opt_binary
+ {
+ $$.set(&type_handler_varchar, $2);
+ }
+ | VARCHAR2 field_length opt_binary
+ {
+ $$.set(&type_handler_varchar, $2);
+ }
+ | nvarchar field_length opt_bin_mod
+ {
+ $$.set(&type_handler_varchar, $2);
+ bincmp_collation(national_charset_info, $3);
+ }
+ | VARBINARY field_length
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_varchar, $2);
+ }
+ | RAW field_length
+ {
+ Lex->charset= &my_charset_bin;
+ $$.set(&type_handler_varchar, $2);
+ }
+ ;
+
+
+sp_param_field_type_string:
+ char opt_field_length_default_sp_param_char opt_binary
+ {
+ $$.set(&type_handler_varchar, $2);
+ }
+ | nchar opt_field_length_default_sp_param_char opt_bin_mod
+ {
+ $$.set(&type_handler_varchar, $2);
+ bincmp_collation(national_charset_info, $3);
+ }
+ | BINARY opt_field_length_default_sp_param_char
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_varchar, $2);
+ }
+ | varchar opt_field_length_default_sp_param_varchar opt_binary
+ {
+ $$.set(&type_handler_varchar, $2);
+ }
+ | VARCHAR2 opt_field_length_default_sp_param_varchar opt_binary
+ {
+ $$.set(&type_handler_varchar, $2);
+ }
+ | nvarchar opt_field_length_default_sp_param_varchar opt_bin_mod
+ {
+ $$.set(&type_handler_varchar, $2);
+ bincmp_collation(national_charset_info, $3);
+ }
+ | VARBINARY opt_field_length_default_sp_param_varchar
+ {
+ Lex->charset= &my_charset_bin;
+ $$.set(&type_handler_varchar, $2);
+ }
+ | RAW opt_field_length_default_sp_param_varchar
+ {
+ Lex->charset= &my_charset_bin;
+ $$.set(&type_handler_varchar, $2);
+ }
+ ;
+
+
+field_type_temporal:
+ YEAR_SYM opt_field_length field_options
+ {
+ if ($2)
+ {
+ errno= 0;
+ ulong length= strtoul($2, NULL, 10);
+ if (errno == 0 && length <= MAX_FIELD_BLOBLENGTH && length != 4)
+ {
+ char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
+ my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX),
+ buff, "YEAR(4)");
+ }
+ }
+ $$.set(&type_handler_year, $2);
+ }
+ | DATE_SYM { $$.set(thd->type_handler_for_date()); }
+ | TIME_SYM opt_field_length
+ {
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_time2) :
+ static_cast<const Type_handler*>(&type_handler_time),
+ $2);
+ }
+ | TIMESTAMP opt_field_length
+ {
+ if (thd->variables.sql_mode & MODE_MAXDB)
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_datetime2) :
+ static_cast<const Type_handler*>(&type_handler_datetime),
+ $2);
+ else
+ {
+ /*
+ Unlike other types TIMESTAMP fields are NOT NULL by default.
+ Unless --explicit-defaults-for-timestamp is given.
+ */
+ if (!opt_explicit_defaults_for_timestamp)
+ Lex->last_field->flags|= NOT_NULL_FLAG;
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_timestamp2):
+ static_cast<const Type_handler*>(&type_handler_timestamp),
+ $2);
+ }
+ }
+ | DATETIME opt_field_length
+ {
+ $$.set(opt_mysql56_temporal_format ?
+ static_cast<const Type_handler*>(&type_handler_datetime2) :
+ static_cast<const Type_handler*>(&type_handler_datetime),
+ $2);
+ }
+ ;
+
+
+field_type_lob:
+ TINYBLOB
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_tiny_blob);
+ }
+ | BLOB_SYM opt_field_length
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_long_blob);
+ }
+ | spatial_type float_options srid_option
+ {
+#ifdef HAVE_SPATIAL
+ Lex->charset=&my_charset_bin;
+ Lex->last_field->geom_type= $1;
+ $$.set(&type_handler_geometry, $2);
+#else
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
+#endif
+ }
+ | MEDIUMBLOB
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_medium_blob);
+ }
+ | LONGBLOB
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_long_blob);
+ }
+ | LONG_SYM VARBINARY
+ {
+ Lex->charset=&my_charset_bin;
+ $$.set(&type_handler_medium_blob);
+ }
+ | LONG_SYM varchar opt_binary
+ { $$.set(&type_handler_medium_blob); }
+ | TINYTEXT opt_binary
+ { $$.set(&type_handler_tiny_blob); }
+ | TEXT_SYM opt_field_length opt_binary
+ { $$.set(&type_handler_blob, $2); }
+ | MEDIUMTEXT opt_binary
+ { $$.set(&type_handler_medium_blob); }
+ | LONGTEXT opt_binary
+ { $$.set(&type_handler_long_blob); }
+ | CLOB opt_binary
+ { $$.set(&type_handler_long_blob); }
+ | LONG_SYM opt_binary
+ { $$.set(&type_handler_medium_blob); }
+ | JSON_SYM opt_binary
+ { $$.set(&type_handler_blob); }
+ ;
+
+field_type_misc:
+ ENUM '(' string_list ')' opt_binary
+ { $$.set(&type_handler_enum); }
+ | SET '(' string_list ')' opt_binary
+ { $$.set(&type_handler_set); }
+ ;
+
+spatial_type:
+ GEOMETRY_SYM { $$= Field::GEOM_GEOMETRY; }
+ | GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; }
+ | POINT_SYM { $$= Field::GEOM_POINT; }
+ | MULTIPOINT { $$= Field::GEOM_MULTIPOINT; }
+ | LINESTRING { $$= Field::GEOM_LINESTRING; }
+ | MULTILINESTRING { $$= Field::GEOM_MULTILINESTRING; }
+ | POLYGON { $$= Field::GEOM_POLYGON; }
+ | MULTIPOLYGON { $$= Field::GEOM_MULTIPOLYGON; }
+ ;
+
+char:
+ CHAR_SYM {}
+ ;
+
+nchar:
+ NCHAR_SYM {}
+ | NATIONAL_SYM CHAR_SYM {}
+ ;
+
+varchar:
+ char VARYING {}
+ | VARCHAR {}
+ ;
+
+nvarchar:
+ NATIONAL_SYM VARCHAR {}
+ | NVARCHAR_SYM {}
+ | NCHAR_SYM VARCHAR {}
+ | NATIONAL_SYM CHAR_SYM VARYING {}
+ | NCHAR_SYM VARYING {}
+ ;
+
+int_type:
+ INT_SYM { $$= &type_handler_long; }
+ | TINYINT { $$= &type_handler_tiny; }
+ | SMALLINT { $$= &type_handler_short; }
+ | MEDIUMINT { $$= &type_handler_int24; }
+ | BIGINT { $$= &type_handler_longlong; }
+ ;
+
+real_type:
+ REAL
+ {
+ $$= thd->variables.sql_mode & MODE_REAL_AS_FLOAT ?
+ static_cast<const Type_handler *>(&type_handler_float) :
+ static_cast<const Type_handler *>(&type_handler_double);
+ }
+ | DOUBLE_SYM { $$= &type_handler_double; }
+ | DOUBLE_SYM PRECISION { $$= &type_handler_double; }
+ ;
+
+srid_option:
+ /* empty */
+ { Lex->last_field->srid= 0; }
+ |
+ REF_SYSTEM_ID_SYM '=' NUM
+ {
+ Lex->last_field->srid=atoi($3.str);
+ }
+ ;
+
+float_options:
+ /* empty */ { $$.set(0, 0); }
+ | field_length { $$.set($1, 0); }
+ | precision { $$= $1; }
+ ;
+
+precision:
+ '(' NUM ',' NUM ')' { $$.set($2.str, $4.str); }
+ ;
+
+field_options:
+ /* empty */ {}
+ | field_opt_list {}
+ ;
+
+field_opt_list:
+ field_opt_list field_option {}
+ | field_option {}
+ ;
+
+field_option:
+ SIGNED_SYM {}
+ | UNSIGNED { Lex->last_field->flags|= UNSIGNED_FLAG;}
+ | ZEROFILL { Lex->last_field->flags|= UNSIGNED_FLAG | ZEROFILL_FLAG; }
+ ;
+
+field_length:
+ '(' LONG_NUM ')' { $$= $2.str; }
+ | '(' ULONGLONG_NUM ')' { $$= $2.str; }
+ | '(' DECIMAL_NUM ')' { $$= $2.str; }
+ | '(' NUM ')' { $$= $2.str; };
+
+opt_field_length:
+ /* empty */ { $$= (char*) 0; /* use default length */ }
+ | field_length { $$= $1; }
+
+opt_field_length_default_1:
+ /* empty */ { $$= (char*) "1"; }
+ | field_length { $$= $1; }
+
+
+/*
+ In sql_mode=ORACLE, a VARCHAR with no length is used
+ in SP parameters and return values and it's translated to VARCHAR(4000),
+ where 4000 is the maximum possible size for VARCHAR.
+
+ In MariaDB the limit for VARCHAR is 65535 bytes.
+ We could translate VARCHAR with no length to VARCHAR(65535), but
+ it would mean that for multi-byte character sets we'd have to translate
+ VARCHAR to MEDIUMTEXT, to guarantee 65535 characters.
+
+ Also we could translate VARCHAR to VARCHAR(16383), where 16383 is
+ the maximum possible length in characters in case of mbmaxlen=4
+ (e.g. utf32, utf16, utf8mb4). However, we'll have character sets with
+ mbmaxlen=5 soon (e.g. gb18030).
+
+ Let's translate VARCHAR to VARCHAR(4000), which covert all possible Oracle
+ values.
+*/
+opt_field_length_default_sp_param_varchar:
+ /* empty */ { $$= (char*) "4000"; }
+ | field_length { $$= $1; }
+
+opt_field_length_default_sp_param_char:
+ /* empty */ { $$= (char*) "2000"; }
+ | field_length { $$= $1; }
+
+opt_precision:
+ /* empty */ { $$.set(0, 0); }
+ | precision { $$= $1; }
+ ;
+
+opt_attribute:
+ /* empty */ {}
+ | opt_attribute_list {}
+ ;
+
+opt_attribute_list:
+ opt_attribute_list attribute {}
+ | attribute
+ ;
+
+attribute:
+ NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
+ | DEFAULT column_default_expr { Lex->last_field->default_value= $2; }
+ | ON UPDATE_SYM NOW_SYM opt_default_time_precision
+ {
+ Item *item= new (thd->mem_root) Item_func_now_local(thd, $4);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ Lex->last_field->on_update= item;
+ }
+ | AUTO_INC { Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
+ | SERIAL_SYM DEFAULT VALUE_SYM
+ {
+ LEX *lex=Lex;
+ lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_KEY_FLAG;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
+ }
+ | COLLATE_SYM collation_name
+ {
+ if (Lex->charset && !my_charset_same(Lex->charset,$2))
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $2->name,Lex->charset->csname));
+ Lex->last_field->charset= $2;
+ }
+ | serial_attribute
+ ;
+
+serial_attribute:
+ not NULL_SYM { Lex->last_field->flags|= NOT_NULL_FLAG; }
+ | opt_primary KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->last_field->flags|= PRI_KEY_FLAG | NOT_NULL_FLAG;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
+ }
+ | vcol_attribute
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
+ new (thd->mem_root)
+ engine_option_value($1, $3, true, &Lex->last_field->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
+ new (thd->mem_root)
+ engine_option_value($1, $3, false, &Lex->last_field->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal real_ulonglong_num
+ {
+ new (thd->mem_root)
+ engine_option_value($1, $3, &Lex->last_field->option_list,
+ &Lex->option_list_last, thd->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (thd->mem_root)
+ engine_option_value($1, &Lex->last_field->option_list, &Lex->option_list_last);
+ }
+ ;
+
+
+type_with_opt_collate:
+ field_type opt_collate
+ {
+ $$= $1;
+
+ if ($2)
+ {
+ if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))
+ MYSQL_YYABORT;
+ }
+ Lex->last_field->set_attributes($1, Lex->charset);
+ }
+ ;
+
+sp_param_type_with_opt_collate:
+ sp_param_field_type opt_collate
+ {
+ $$= $1;
+ if ($2)
+ {
+ if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))
+ MYSQL_YYABORT;
+ }
+ Lex->last_field->set_attributes($1, Lex->charset);
+ }
+ ;
+
+charset:
+ CHAR_SYM SET {}
+ | CHARSET {}
+ ;
+
+charset_name:
+ ident_or_text
+ {
+ if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
+ }
+ | BINARY { $$= &my_charset_bin; }
+ ;
+
+charset_name_or_default:
+ charset_name { $$=$1; }
+ | DEFAULT { $$=NULL; }
+ ;
+
+opt_load_data_charset:
+ /* Empty */ { $$= NULL; }
+ | charset charset_name_or_default { $$= $2; }
+ ;
+
+old_or_new_charset_name:
+ ident_or_text
+ {
+ if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
+ !($$=get_old_charset_by_name($1.str)))
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
+ }
+ | BINARY { $$= &my_charset_bin; }
+ ;
+
+old_or_new_charset_name_or_default:
+ old_or_new_charset_name { $$=$1; }
+ | DEFAULT { $$=NULL; }
+ ;
+
+collation_name:
+ ident_or_text
+ {
+ if (!($$= mysqld_collation_get_by_name($1.str)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_collate:
+ /* empty */ { $$=NULL; }
+ | COLLATE_SYM collation_name_or_default { $$=$2; }
+ ;
+
+collation_name_or_default:
+ collation_name { $$=$1; }
+ | DEFAULT { $$=NULL; }
+ ;
+
+opt_default:
+ /* empty */ {}
+ | DEFAULT {}
+ ;
+
+charset_or_alias:
+ charset charset_name { $$= $2; }
+ | ASCII_SYM { $$= &my_charset_latin1; }
+ | UNICODE_SYM
+ {
+ if (!($$= get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0))))
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"));
+ }
+ ;
+
+opt_binary:
+ /* empty */ { bincmp_collation(NULL, false); }
+ | BYTE_SYM { bincmp_collation(&my_charset_bin, false); }
+ | charset_or_alias opt_bin_mod { bincmp_collation($1, $2); }
+ | BINARY { bincmp_collation(NULL, true); }
+ | BINARY charset_or_alias { bincmp_collation($2, true); }
+ ;
+
+opt_bin_mod:
+ /* empty */ { $$= false; }
+ | BINARY { $$= true; }
+ ;
+
+ws_nweights:
+ '(' real_ulong_num
+ {
+ if ($2 == 0)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ ')'
+ { $$= $2; }
+ ;
+
+ws_level_flag_desc:
+ ASC { $$= 0; }
+ | DESC { $$= 1 << MY_STRXFRM_DESC_SHIFT; }
+ ;
+
+ws_level_flag_reverse:
+ REVERSE_SYM { $$= 1 << MY_STRXFRM_REVERSE_SHIFT; } ;
+
+ws_level_flags:
+ /* empty */ { $$= 0; }
+ | ws_level_flag_desc { $$= $1; }
+ | ws_level_flag_desc ws_level_flag_reverse { $$= $1 | $2; }
+ | ws_level_flag_reverse { $$= $1 ; }
+ ;
+
+ws_level_number:
+ real_ulong_num
+ {
+ $$= $1 < 1 ? 1 : ($1 > MY_STRXFRM_NLEVELS ? MY_STRXFRM_NLEVELS : $1);
+ $$--;
+ }
+ ;
+
+ws_level_list_item:
+ ws_level_number ws_level_flags
+ {
+ $$= (1 | $2) << $1;
+ }
+ ;
+
+ws_level_list:
+ ws_level_list_item { $$= $1; }
+ | ws_level_list ',' ws_level_list_item { $$|= $3; }
+ ;
+
+ws_level_range:
+ ws_level_number '-' ws_level_number
+ {
+ uint start= $1;
+ uint end= $3;
+ for ($$= 0; start <= end; start++)
+ $$|= (1 << start);
+ }
+ ;
+
+ws_level_list_or_range:
+ ws_level_list { $$= $1; }
+ | ws_level_range { $$= $1; }
+ ;
+
+opt_ws_levels:
+ /* empty*/ { $$= 0; }
+ | LEVEL_SYM ws_level_list_or_range { $$= $2; }
+ ;
+
+opt_primary:
+ /* empty */
+ | PRIMARY_SYM
+ ;
+
+references:
+ REFERENCES
+ table_ident
+ opt_ref_list
+ opt_match_clause
+ opt_on_update_delete
+ {
+ $$=$2;
+ }
+ ;
+
+opt_ref_list:
+ /* empty */
+ { Lex->ref_list.empty(); }
+ | '(' ref_list ')'
+ ;
+
+ref_list:
+ ref_list ',' ident
+ {
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec(&$3, 0);
+ if (key == NULL)
+ MYSQL_YYABORT;
+ Lex->ref_list.push_back(key, thd->mem_root);
+ }
+ | ident
+ {
+ Key_part_spec *key= new (thd->mem_root) Key_part_spec(&$1, 0);
+ if (key == NULL)
+ MYSQL_YYABORT;
+ LEX *lex= Lex;
+ lex->ref_list.empty();
+ lex->ref_list.push_back(key, thd->mem_root);
+ }
+ ;
+
+opt_match_clause:
+ /* empty */
+ { Lex->fk_match_option= Foreign_key::FK_MATCH_UNDEF; }
+ | MATCH FULL
+ { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; }
+ | MATCH PARTIAL
+ { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; }
+ | MATCH SIMPLE_SYM
+ { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; }
+ ;
+
+opt_on_update_delete:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ lex->fk_update_opt= FK_OPTION_UNDEF;
+ lex->fk_delete_opt= FK_OPTION_UNDEF;
+ }
+ | ON UPDATE_SYM delete_option
+ {
+ LEX *lex= Lex;
+ lex->fk_update_opt= $3;
+ lex->fk_delete_opt= FK_OPTION_UNDEF;
+ }
+ | ON DELETE_SYM delete_option
+ {
+ LEX *lex= Lex;
+ lex->fk_update_opt= FK_OPTION_UNDEF;
+ lex->fk_delete_opt= $3;
+ }
+ | ON UPDATE_SYM delete_option
+ ON DELETE_SYM delete_option
+ {
+ LEX *lex= Lex;
+ lex->fk_update_opt= $3;
+ lex->fk_delete_opt= $6;
+ }
+ | ON DELETE_SYM delete_option
+ ON UPDATE_SYM delete_option
+ {
+ LEX *lex= Lex;
+ lex->fk_update_opt= $6;
+ lex->fk_delete_opt= $3;
+ }
+ ;
+
+delete_option:
+ RESTRICT { $$= FK_OPTION_RESTRICT; }
+ | CASCADE { $$= FK_OPTION_CASCADE; }
+ | SET NULL_SYM { $$= FK_OPTION_SET_NULL; }
+ | NO_SYM ACTION { $$= FK_OPTION_NO_ACTION; }
+ | SET DEFAULT { $$= FK_OPTION_SET_DEFAULT; }
+ ;
+
+constraint_key_type:
+ PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
+ | UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; }
+ ;
+
+key_or_index:
+ KEY_SYM {}
+ | INDEX_SYM {}
+ ;
+
+opt_key_or_index:
+ /* empty */ {}
+ | key_or_index
+ ;
+
+keys_or_index:
+ KEYS {}
+ | INDEX_SYM {}
+ | INDEXES {}
+ ;
+
+opt_unique:
+ /* empty */ { $$= Key::MULTIPLE; }
+ | UNIQUE_SYM { $$= Key::UNIQUE; }
+ ;
+
+fulltext:
+ FULLTEXT_SYM { $$= Key::FULLTEXT;}
+ ;
+
+spatial:
+ SPATIAL_SYM
+ {
+#ifdef HAVE_SPATIAL
+ $$= Key::SPATIAL;
+#else
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
+#endif
+ }
+ ;
+
+normal_key_options:
+ /* empty */ {}
+ | normal_key_opts { Lex->last_key->option_list= Lex->option_list; }
+ ;
+
+fulltext_key_options:
+ /* empty */ {}
+ | fulltext_key_opts { Lex->last_key->option_list= Lex->option_list; }
+ ;
+
+spatial_key_options:
+ /* empty */ {}
+ | spatial_key_opts { Lex->last_key->option_list= Lex->option_list; }
+ ;
+
+normal_key_opts:
+ normal_key_opt
+ | normal_key_opts normal_key_opt
+ ;
+
+spatial_key_opts:
+ spatial_key_opt
+ | spatial_key_opts spatial_key_opt
+ ;
+
+fulltext_key_opts:
+ fulltext_key_opt
+ | fulltext_key_opts fulltext_key_opt
+ ;
+
+opt_USING_key_algorithm:
+ /* Empty*/ { $$= HA_KEY_ALG_UNDEF; }
+ | USING btree_or_rtree { $$= $2; }
+
+/* TYPE is a valid identifier, so it's handled differently than USING */
+opt_key_algorithm_clause:
+ /* Empty*/ { $$= HA_KEY_ALG_UNDEF; }
+ | USING btree_or_rtree { $$= $2; }
+ | TYPE_SYM btree_or_rtree { $$= $2; }
+
+key_using_alg:
+ USING btree_or_rtree
+ { Lex->last_key->key_create_info.algorithm= $2; }
+ | TYPE_SYM btree_or_rtree
+ { Lex->last_key->key_create_info.algorithm= $2; }
+ ;
+
+all_key_opt:
+ KEY_BLOCK_SIZE opt_equal ulong_num
+ { Lex->last_key->key_create_info.block_size= $3; }
+ | COMMENT_SYM TEXT_STRING_sys
+ { Lex->last_key->key_create_info.comment= $2; }
+ | IDENT_sys equal TEXT_STRING_sys
+ {
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
+ new (thd->mem_root)
+ engine_option_value($1, $3, true, &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal ident
+ {
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
+ new (thd->mem_root)
+ engine_option_value($1, $3, false, &Lex->option_list,
+ &Lex->option_list_last);
+ }
+ | IDENT_sys equal real_ulonglong_num
+ {
+ new (thd->mem_root)
+ engine_option_value($1, $3, &Lex->option_list,
+ &Lex->option_list_last, thd->mem_root);
+ }
+ | IDENT_sys equal DEFAULT
+ {
+ new (thd->mem_root)
+ engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
+ }
+ ;
+
+normal_key_opt:
+ all_key_opt
+ | key_using_alg
+ ;
+
+spatial_key_opt:
+ all_key_opt
+ ;
+
+fulltext_key_opt:
+ all_key_opt
+ | WITH PARSER_SYM IDENT_sys
+ {
+ if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
+ Lex->last_key->key_create_info.parser_name= $3;
+ else
+ my_yyabort_error((ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str));
+ }
+ ;
+
+btree_or_rtree:
+ BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
+ | RTREE_SYM { $$= HA_KEY_ALG_RTREE; }
+ | HASH_SYM { $$= HA_KEY_ALG_HASH; }
+ ;
+
+key_list:
+ key_list ',' key_part order_dir
+ {
+ Lex->last_key->columns.push_back($3, thd->mem_root);
+ }
+ | key_part order_dir
+ {
+ Lex->last_key->columns.push_back($1, thd->mem_root);
+ }
+ ;
+
+key_part:
+ ident
+ {
+ $$= new (thd->mem_root) Key_part_spec(&$1, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ident '(' NUM ')'
+ {
+ int key_part_len= atoi($3.str);
+ if (!key_part_len)
+ my_yyabort_error((ER_KEY_PART_0, MYF(0), $1.str));
+ $$= new (thd->mem_root) Key_part_spec(&$1, (uint) key_part_len);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_ident:
+ /* empty */ { $$= null_clex_str; }
+ | field_ident { $$= $1; }
+ ;
+
+opt_component:
+ /* empty */ { $$= null_clex_str; }
+ | '.' ident { $$= $2; }
+ ;
+
+string_list:
+ text_string
+ { Lex->last_field->interval_list.push_back($1, thd->mem_root); }
+ | string_list ',' text_string
+ { Lex->last_field->interval_list.push_back($3, thd->mem_root); };
+
+/*
+** Alter table
+*/
+
+alter:
+ ALTER
+ {
+ Lex->name= null_clex_str;
+ Lex->table_type= TABLE_TYPE_UNKNOWN;
+ Lex->sql_command= SQLCOM_ALTER_TABLE;
+ Lex->duplicates= DUP_ERROR;
+ Lex->select_lex.init_order();
+ Lex->create_info.init();
+ Lex->create_info.row_type= ROW_TYPE_NOT_USED;
+ Lex->alter_info.reset();
+ Lex->no_write_to_binlog= 0;
+ Lex->create_info.storage_media= HA_SM_DEFAULT;
+ DBUG_ASSERT(!Lex->m_sql_cmd);
+ }
+ alter_options TABLE_SYM table_ident
+ {
+ if (!Lex->select_lex.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_UPGRADABLE))
+ MYSQL_YYABORT;
+ Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
+ Lex->create_last_non_select_table= Lex->last_table();
+ }
+ alter_commands
+ {
+ if (!Lex->m_sql_cmd)
+ {
+ /* Create a generic ALTER TABLE statment. */
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ }
+ | ALTER DATABASE ident_or_empty
+ {
+ Lex->create_info.default_table_charset= NULL;
+ Lex->create_info.used_fields= 0;
+ }
+ create_database_options
+ {
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_ALTER_DB;
+ lex->name= $3;
+ if (lex->name.str == NULL &&
+ lex->copy_db_to(&lex->name.str, &lex->name.length))
+ MYSQL_YYABORT;
+ }
+ | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM
+ {
+ LEX *lex= Lex;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "DATABASE"));
+ lex->sql_command= SQLCOM_ALTER_DB_UPGRADE;
+ lex->name= $3;
+ }
+ | ALTER PROCEDURE_SYM sp_name
+ {
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
+ lex->sp_chistics.init();
+ }
+ sp_a_chistics
+ {
+ LEX *lex=Lex;
+
+ lex->sql_command= SQLCOM_ALTER_PROCEDURE;
+ lex->spname= $3;
+ }
+ | ALTER FUNCTION_SYM sp_name
+ {
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+ lex->sp_chistics.init();
+ }
+ sp_a_chistics
+ {
+ LEX *lex=Lex;
+
+ lex->sql_command= SQLCOM_ALTER_FUNCTION;
+ lex->spname= $3;
+ }
+ | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident
+ {
+ if (Lex->add_alter_view(thd, $2, $4, $6))
+ MYSQL_YYABORT;
+ }
+ view_list_opt AS view_select
+ {}
+ | ALTER definer_opt opt_view_suid VIEW_SYM table_ident
+ /*
+ We have two separate rules for ALTER VIEW rather that
+ optional view_algorithm above, to resolve the ambiguity
+ with the ALTER EVENT below.
+ */
+ {
+ if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))
+ MYSQL_YYABORT;
+ }
+ view_list_opt AS view_select
+ {}
+ | ALTER definer_opt remember_name EVENT_SYM sp_name
+ {
+ /*
+ It is safe to use Lex->spname because
+ ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
+ is not allowed. Lex->spname is used in the case of RENAME TO
+ If it had to be supported spname had to be added to
+ Event_parse_data.
+ */
+
+ if (!(Lex->event_parse_data= Event_parse_data::new_instance(thd)))
+ MYSQL_YYABORT;
+ Lex->event_parse_data->identifier= $5;
+
+ Lex->sql_command= SQLCOM_ALTER_EVENT;
+ Lex->stmt_definition_begin= $3;
+ }
+ ev_alter_on_schedule_completion
+ opt_ev_rename_to
+ opt_ev_status
+ opt_ev_comment
+ opt_ev_sql_stmt
+ {
+ if (!($7 || $8 || $9 || $10 || $11))
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ /*
+ sql_command is set here because some rules in ev_sql_stmt
+ can overwrite it
+ */
+ Lex->sql_command= SQLCOM_ALTER_EVENT;
+ Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr();
+ }
+ | ALTER TABLESPACE alter_tablespace_info
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_cmd_type= ALTER_TABLESPACE;
+ }
+ | ALTER LOGFILE_SYM GROUP_SYM alter_logfile_group_info
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_cmd_type= ALTER_LOGFILE_GROUP;
+ }
+ | ALTER TABLESPACE change_tablespace_info
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_cmd_type= CHANGE_FILE_TABLESPACE;
+ }
+ | ALTER TABLESPACE change_tablespace_access
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_cmd_type= ALTER_ACCESS_MODE_TABLESPACE;
+ }
+ | ALTER SERVER_SYM ident_or_text
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_ALTER_SERVER;
+ lex->server_options.reset($3);
+ } OPTIONS_SYM '(' server_options_list ')' { }
+ /* ALTER USER foo is allowed for MySQL compatibility. */
+ | ALTER opt_if_exists USER_SYM clear_privileges grant_list
+ opt_require_clause opt_resource_options
+ {
+ Lex->create_info.set($2);
+ Lex->sql_command= SQLCOM_ALTER_USER;
+ }
+ | ALTER SEQUENCE_SYM opt_if_exists_table_element
+ {
+ LEX *lex= Lex;
+ lex->name= null_clex_str;
+ lex->table_type= TABLE_TYPE_UNKNOWN;
+ lex->sql_command= SQLCOM_ALTER_SEQUENCE;
+ lex->create_info.init();
+ lex->no_write_to_binlog= 0;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ }
+ table_ident
+ {
+ LEX *lex= Lex;
+ if (!(lex->create_info.seq_create_info= new (thd->mem_root)
+ sequence_definition()) ||
+ !lex->select_lex.add_table_to_list(thd, $5, NULL,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE, MDL_EXCLUSIVE))
+ MYSQL_YYABORT;
+ }
+ sequence_defs
+ {
+ /* Create a generic ALTER SEQUENCE statment. */
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence();
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+ev_alter_on_schedule_completion:
+ /* empty */ { $$= 0;}
+ | ON SCHEDULE_SYM ev_schedule_time { $$= 1; }
+ | ev_on_completion { $$= 1; }
+ | ON SCHEDULE_SYM ev_schedule_time ev_on_completion { $$= 1; }
+ ;
+
+opt_ev_rename_to:
+ /* empty */ { $$= 0;}
+ | RENAME TO_SYM sp_name
+ {
+ /*
+ Use lex's spname to hold the new name.
+ The original name is in the Event_parse_data object
+ */
+ Lex->spname= $3;
+ $$= 1;
+ }
+ ;
+
+opt_ev_sql_stmt:
+ /* empty*/ { $$= 0;}
+ | DO_SYM ev_sql_stmt { $$= 1; }
+ ;
+
+ident_or_empty:
+ /* empty */ { $$= null_clex_str; }
+ | ident { $$= $1; }
+ ;
+
+alter_commands:
+ /* empty */
+ | DISCARD TABLESPACE
+ {
+ Lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_discard_import_tablespace(
+ Sql_cmd_discard_import_tablespace::DISCARD_TABLESPACE);
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ | IMPORT TABLESPACE
+ {
+ Lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_discard_import_tablespace(
+ Sql_cmd_discard_import_tablespace::IMPORT_TABLESPACE);
+ if (Lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ | alter_list
+ opt_partitioning
+ | alter_list
+ remove_partitioning
+ | remove_partitioning
+ | partitioning
+/*
+ This part was added for release 5.1 by Mikael Ronstrm.
+ From here we insert a number of commands to manage the partitions of a
+ partitioned table such as adding partitions, dropping partitions,
+ reorganising partitions in various manners. In future releases the list
+ will be longer.
+*/
+ | add_partition_rule
+ | DROP PARTITION_SYM opt_if_exists alt_part_name_list
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_DROP_PARTITION;
+ DBUG_ASSERT(!Lex->if_exists());
+ Lex->create_info.add($3);
+ }
+ | REBUILD_SYM PARTITION_SYM opt_no_write_to_binlog
+ all_or_alt_part_name_list
+ {
+ LEX *lex= Lex;
+ lex->alter_info.flags|= Alter_info::ALTER_REBUILD_PARTITION;
+ lex->no_write_to_binlog= $3;
+ }
+ | OPTIMIZE PARTITION_SYM opt_no_write_to_binlog
+ all_or_alt_part_name_list
+ {
+ LEX *lex= thd->lex;
+ lex->no_write_to_binlog= $3;
+ lex->check_opt.init();
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_optimize_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ opt_no_write_to_binlog
+ | ANALYZE_SYM PARTITION_SYM opt_no_write_to_binlog
+ all_or_alt_part_name_list
+ {
+ LEX *lex= thd->lex;
+ lex->no_write_to_binlog= $3;
+ lex->check_opt.init();
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_analyze_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ | CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
+ {
+ LEX *lex= thd->lex;
+ lex->check_opt.init();
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_check_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ opt_mi_check_type
+ | REPAIR PARTITION_SYM opt_no_write_to_binlog
+ all_or_alt_part_name_list
+ {
+ LEX *lex= thd->lex;
+ lex->no_write_to_binlog= $3;
+ lex->check_opt.init();
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_repair_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ opt_mi_repair_type
+ | COALESCE PARTITION_SYM opt_no_write_to_binlog real_ulong_num
+ {
+ LEX *lex= Lex;
+ lex->alter_info.flags|= Alter_info::ALTER_COALESCE_PARTITION;
+ lex->no_write_to_binlog= $3;
+ lex->alter_info.num_parts= $4;
+ }
+ | TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
+ {
+ LEX *lex= thd->lex;
+ lex->check_opt.init();
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_truncate_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ | reorg_partition_rule
+ | EXCHANGE_SYM PARTITION_SYM alt_part_name_item
+ WITH TABLE_SYM table_ident have_partitioning
+ {
+ LEX *lex= thd->lex;
+ size_t dummy;
+ lex->select_lex.db=$6->db.str;
+ if (lex->select_lex.db == NULL &&
+ lex->copy_db_to(&lex->select_lex.db, &dummy))
+ {
+ MYSQL_YYABORT;
+ }
+ lex->name= $6->table;
+ lex->alter_info.flags|= Alter_info::ALTER_EXCHANGE_PARTITION;
+ if (!lex->select_lex.add_table_to_list(thd, $6, NULL,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_NO_WRITE))
+ MYSQL_YYABORT;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root)
+ Sql_cmd_alter_table_exchange_partition();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+remove_partitioning:
+ REMOVE_SYM PARTITIONING_SYM
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_REMOVE_PARTITIONING;
+ }
+ ;
+
+all_or_alt_part_name_list:
+ ALL
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_ALL_PARTITION;
+ }
+ | alt_part_name_list
+ ;
+
+add_partition_rule:
+ ADD PARTITION_SYM opt_if_not_exists
+ opt_no_write_to_binlog
+ {
+ LEX *lex= Lex;
+ lex->part_info= new (thd->mem_root) partition_info();
+ if (!lex->part_info)
+ {
+ mem_alloc_error(sizeof(partition_info));
+ MYSQL_YYABORT;
+ }
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_PARTITION;
+ DBUG_ASSERT(!Lex->create_info.if_not_exists());
+ lex->create_info.set($3);
+ lex->no_write_to_binlog= $4;
+ }
+ add_part_extra
+ {}
+ ;
+
+add_part_extra:
+ /* empty */
+ | '(' part_def_list ')'
+ {
+ LEX *lex= Lex;
+ lex->part_info->num_parts= lex->part_info->partitions.elements;
+ }
+ | PARTITIONS_SYM real_ulong_num
+ {
+ Lex->part_info->num_parts= $2;
+ }
+ ;
+
+reorg_partition_rule:
+ REORGANIZE_SYM PARTITION_SYM opt_no_write_to_binlog
+ {
+ LEX *lex= Lex;
+ lex->part_info= new (thd->mem_root) partition_info();
+ if (!lex->part_info)
+ {
+ mem_alloc_error(sizeof(partition_info));
+ MYSQL_YYABORT;
+ }
+ lex->no_write_to_binlog= $3;
+ }
+ reorg_parts_rule
+ ;
+
+reorg_parts_rule:
+ /* empty */
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_TABLE_REORG;
+ }
+ | alt_part_name_list
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_REORGANIZE_PARTITION;
+ }
+ INTO '(' part_def_list ')'
+ {
+ partition_info *part_info= Lex->part_info;
+ part_info->num_parts= part_info->partitions.elements;
+ }
+ ;
+
+alt_part_name_list:
+ alt_part_name_item {}
+ | alt_part_name_list ',' alt_part_name_item {}
+ ;
+
+alt_part_name_item:
+ ident
+ {
+ if (Lex->alter_info.partition_names.push_back($1.str,
+ thd->mem_root))
+ {
+ mem_alloc_error(1);
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+/*
+ End of management of partition commands
+*/
+
+alter_list:
+ alter_list_item
+ | alter_list ',' alter_list_item
+ ;
+
+add_column:
+ ADD opt_column opt_if_not_exists_table_element
+ {
+ LEX *lex=Lex;
+ lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN;
+ }
+ ;
+
+alter_list_item:
+ add_column column_def opt_place
+ {
+ Lex->create_last_non_select_table= Lex->last_table();
+ $2->after= $3;
+ }
+ | ADD key_def
+ {
+ Lex->create_last_non_select_table= Lex->last_table();
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
+ }
+ | add_column '(' create_field_list ')'
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN |
+ Alter_info::ALTER_ADD_INDEX;
+ }
+ | ADD constraint_def
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_CHECK_CONSTRAINT;
+ }
+ | ADD CONSTRAINT IF_SYM not EXISTS field_ident check_constraint
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_ADD_CHECK_CONSTRAINT;
+ Lex->add_constraint(&$6, $7, TRUE);
+ }
+ | CHANGE opt_column opt_if_exists_table_element field_ident
+ field_spec opt_place
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
+ Lex->create_last_non_select_table= Lex->last_table();
+ $5->change= $4;
+ $5->after= $6;
+ }
+ | MODIFY_SYM opt_column opt_if_exists_table_element
+ field_spec opt_place
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
+ Lex->create_last_non_select_table= Lex->last_table();
+ $4->change= $4->field_name;
+ $4->after= $5;
+ }
+ | DROP opt_column opt_if_exists_table_element field_ident opt_restrict
+ {
+ LEX *lex=Lex;
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::COLUMN, $4.str, $3));
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_COLUMN;
+ }
+ | DROP CONSTRAINT opt_if_exists_table_element field_ident
+ {
+ LEX *lex=Lex;
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::CHECK_CONSTRAINT,
+ $4.str, $3));
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_CHECK_CONSTRAINT;
+ }
+ | DROP FOREIGN KEY_SYM opt_if_exists_table_element field_ident
+ {
+ LEX *lex=Lex;
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::FOREIGN_KEY, $5.str, $4));
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::DROP_FOREIGN_KEY;
+ }
+ | DROP PRIMARY_SYM KEY_SYM
+ {
+ LEX *lex=Lex;
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::KEY, primary_key_name,
+ FALSE));
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX;
+ }
+ | DROP key_or_index opt_if_exists_table_element field_ident
+ {
+ LEX *lex=Lex;
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::KEY, $4.str, $3));
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_DROP_INDEX;
+ }
+ | DISABLE_SYM KEYS
+ {
+ LEX *lex=Lex;
+ lex->alter_info.keys_onoff= Alter_info::DISABLE;
+ lex->alter_info.flags|= Alter_info::ALTER_KEYS_ONOFF;
+ }
+ | ENABLE_SYM KEYS
+ {
+ LEX *lex=Lex;
+ lex->alter_info.keys_onoff= Alter_info::ENABLE;
+ lex->alter_info.flags|= Alter_info::ALTER_KEYS_ONOFF;
+ }
+ | ALTER opt_column field_ident SET DEFAULT column_default_expr
+ {
+ LEX *lex=Lex;
+ Alter_column *ac= new (thd->mem_root) Alter_column($3.str,$6);
+ if (ac == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.alter_list.push_back(ac, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT;
+ }
+ | ALTER opt_column field_ident DROP DEFAULT
+ {
+ LEX *lex=Lex;
+ Alter_column *ac= (new (thd->mem_root)
+ Alter_column($3.str, (Virtual_column_info*) 0));
+ if (ac == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.alter_list.push_back(ac, thd->mem_root);
+ lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN_DEFAULT;
+ }
+ | RENAME opt_to table_ident
+ {
+ LEX *lex=Lex;
+ size_t dummy;
+ lex->select_lex.db=$3->db.str;
+ if (lex->select_lex.db == NULL &&
+ lex->copy_db_to(&lex->select_lex.db, &dummy))
+ {
+ MYSQL_YYABORT;
+ }
+ if (check_table_name($3->table.str,$3->table.length, FALSE) ||
+ ($3->db.str && check_db_name((LEX_STRING*) &$3->db)))
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3->table.str));
+ lex->name= $3->table;
+ lex->alter_info.flags|= Alter_info::ALTER_RENAME;
+ }
+ | CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
+ {
+ if (!$4)
+ {
+ $4= thd->variables.collation_database;
+ }
+ $5= $5 ? $5 : $4;
+ if (!my_charset_same($4,$5))
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $5->name, $4->csname));
+ if (Lex->create_info.add_alter_list_item_convert_to_charset($5))
+ MYSQL_YYABORT;
+ Lex->alter_info.flags|= Alter_info::ALTER_OPTIONS;
+ }
+ | create_table_options_space_separated
+ {
+ LEX *lex=Lex;
+ lex->alter_info.flags|= Alter_info::ALTER_OPTIONS;
+ if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
+ !lex->create_info.db_type)
+ {
+ lex->create_info.used_fields&= ~HA_CREATE_USED_ENGINE;
+ }
+ }
+ | FORCE_SYM
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_RECREATE;
+ }
+ | alter_order_clause
+ {
+ LEX *lex=Lex;
+ lex->alter_info.flags|= Alter_info::ALTER_ORDER;
+ }
+ | alter_algorithm_option
+ | alter_lock_option
+ ;
+
+opt_index_lock_algorithm:
+ /* empty */
+ | alter_lock_option
+ | alter_algorithm_option
+ | alter_lock_option alter_algorithm_option
+ | alter_algorithm_option alter_lock_option
+
+alter_algorithm_option:
+ ALGORITHM_SYM opt_equal DEFAULT
+ {
+ Lex->alter_info.requested_algorithm=
+ Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT;
+ }
+ | ALGORITHM_SYM opt_equal ident
+ {
+ if (Lex->alter_info.set_requested_algorithm(&$3))
+ my_yyabort_error((ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str));
+ }
+ ;
+
+alter_lock_option:
+ LOCK_SYM opt_equal DEFAULT
+ {
+ Lex->alter_info.requested_lock=
+ Alter_info::ALTER_TABLE_LOCK_DEFAULT;
+ }
+ | LOCK_SYM opt_equal ident
+ {
+ if (Lex->alter_info.set_requested_lock(&$3))
+ my_yyabort_error((ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str));
+ }
+ ;
+
+opt_column:
+ /* empty */ {}
+ | COLUMN_SYM {}
+ ;
+
+opt_ignore:
+ /* empty */ { Lex->ignore= 0;}
+ | IGNORE_SYM { Lex->ignore= 1;}
+ ;
+
+alter_options:
+ { Lex->ignore= 0;} alter_options_part2
+ ;
+
+alter_options_part2:
+ /* empty */
+ | alter_option_list
+ ;
+
+alter_option_list:
+ alter_option_list alter_option
+ | alter_option
+ ;
+
+alter_option:
+ IGNORE_SYM { Lex->ignore= 1;}
+ | ONLINE_SYM
+ {
+ Lex->alter_info.requested_lock=
+ Alter_info::ALTER_TABLE_LOCK_NONE;
+ }
+
+
+opt_restrict:
+ /* empty */ { Lex->drop_mode= DROP_DEFAULT; }
+ | RESTRICT { Lex->drop_mode= DROP_RESTRICT; }
+ | CASCADE { Lex->drop_mode= DROP_CASCADE; }
+ ;
+
+opt_place:
+ /* empty */ { $$= null_clex_str; }
+ | AFTER_SYM ident
+ {
+ $$= $2;
+ Lex->alter_info.flags |= Alter_info::ALTER_COLUMN_ORDER;
+ }
+ | FIRST_SYM
+ {
+ $$.str= first_keyword;
+ $$.length= 5; /* Length of "first" */
+ Lex->alter_info.flags |= Alter_info::ALTER_COLUMN_ORDER;
+ }
+ ;
+
+opt_to:
+ /* empty */ {}
+ | TO_SYM {}
+ | '=' {}
+ | AS {}
+ ;
+
+slave:
+ START_SYM SLAVE optional_connection_name slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_START;
+ lex->type = 0;
+ /* If you change this code don't forget to update SLAVE START too */
+ }
+ slave_until
+ {}
+ | START_SYM ALL SLAVES slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_ALL_START;
+ lex->type = 0;
+ /* If you change this code don't forget to update STOP SLAVE too */
+ }
+ {}
+ | STOP_SYM SLAVE optional_connection_name slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->type = 0;
+ /* If you change this code don't forget to update SLAVE STOP too */
+ }
+ | STOP_SYM ALL SLAVES slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_ALL_STOP;
+ lex->type = 0;
+ /* If you change this code don't forget to update SLAVE STOP too */
+ }
+ ;
+
+start:
+ START_SYM TRANSACTION_SYM opt_start_transaction_option_list
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_BEGIN;
+ /* READ ONLY and READ WRITE are mutually exclusive. */
+ if (($3 & MYSQL_START_TRANS_OPT_READ_WRITE) &&
+ ($3 & MYSQL_START_TRANS_OPT_READ_ONLY))
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ lex->start_transaction_opt= $3;
+ }
+ ;
+
+opt_start_transaction_option_list:
+ /* empty */
+ {
+ $$= 0;
+ }
+ | start_transaction_option_list
+ {
+ $$= $1;
+ }
+ ;
+
+start_transaction_option_list:
+ start_transaction_option
+ {
+ $$= $1;
+ }
+ | start_transaction_option_list ',' start_transaction_option
+ {
+ $$= $1 | $3;
+ }
+ ;
+
+start_transaction_option:
+ WITH CONSISTENT_SYM SNAPSHOT_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
+ }
+ | READ_SYM ONLY_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_READ_ONLY;
+ }
+ | READ_SYM WRITE_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_READ_WRITE;
+ }
+ ;
+
+slave_thread_opts:
+ { Lex->slave_thd_opt= 0; }
+ slave_thread_opt_list
+ {}
+ ;
+
+slave_thread_opt_list:
+ slave_thread_opt
+ | slave_thread_opt_list ',' slave_thread_opt
+ ;
+
+slave_thread_opt:
+ /*empty*/ {}
+ | SQL_THREAD { Lex->slave_thd_opt|=SLAVE_SQL; }
+ | RELAY_THREAD { Lex->slave_thd_opt|=SLAVE_IO; }
+ ;
+
+slave_until:
+ /*empty*/ {}
+ | UNTIL_SYM slave_until_opts
+ {
+ LEX *lex=Lex;
+ if (((lex->mi.log_file_name || lex->mi.pos) &&
+ (lex->mi.relay_log_name || lex->mi.relay_log_pos)) ||
+ !((lex->mi.log_file_name && lex->mi.pos) ||
+ (lex->mi.relay_log_name && lex->mi.relay_log_pos)))
+ my_yyabort_error((ER_BAD_SLAVE_UNTIL_COND, MYF(0)));
+ }
+ | UNTIL_SYM MASTER_GTID_POS_SYM '=' TEXT_STRING_sys
+ {
+ Lex->mi.gtid_pos_str = $4;
+ }
+ ;
+
+slave_until_opts:
+ master_file_def
+ | slave_until_opts ',' master_file_def
+ ;
+
+checksum:
+ CHECKSUM_SYM table_or_tables
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_CHECKSUM;
+ /* Will be overridden during execution. */
+ YYPS->m_lock_type= TL_UNLOCK;
+ }
+ table_list opt_checksum_type
+ {}
+ ;
+
+opt_checksum_type:
+ /* nothing */ { Lex->check_opt.flags= 0; }
+ | QUICK { Lex->check_opt.flags= T_QUICK; }
+ | EXTENDED_SYM { Lex->check_opt.flags= T_EXTEND; }
+ ;
+
+repair_table_or_view:
+ table_or_tables table_list opt_mi_repair_type
+ | VIEW_SYM
+ { Lex->table_type= TABLE_TYPE_VIEW; }
+ table_list opt_view_repair_type
+ ;
+
+repair:
+ REPAIR opt_no_write_to_binlog
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_REPAIR;
+ lex->no_write_to_binlog= $2;
+ lex->check_opt.init();
+ lex->alter_info.reset();
+ /* Will be overridden during execution. */
+ YYPS->m_lock_type= TL_UNLOCK;
+ }
+ repair_table_or_view
+ {
+ LEX* lex= thd->lex;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_mi_repair_type:
+ /* empty */ { Lex->check_opt.flags = T_MEDIUM; }
+ | mi_repair_types {}
+ ;
+
+mi_repair_types:
+ mi_repair_type {}
+ | mi_repair_type mi_repair_types {}
+ ;
+
+mi_repair_type:
+ QUICK { Lex->check_opt.flags|= T_QUICK; }
+ | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
+ | USE_FRM { Lex->check_opt.sql_flags|= TT_USEFRM; }
+ ;
+
+opt_view_repair_type:
+ /* empty */ { }
+ | FROM MYSQL_SYM { Lex->check_opt.sql_flags|= TT_FROM_MYSQL; }
+ ;
+
+analyze:
+ ANALYZE_SYM opt_no_write_to_binlog table_or_tables
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_ANALYZE;
+ lex->no_write_to_binlog= $2;
+ lex->check_opt.init();
+ lex->alter_info.reset();
+ /* Will be overridden during execution. */
+ YYPS->m_lock_type= TL_UNLOCK;
+ }
+ analyze_table_list
+ {
+ LEX* lex= thd->lex;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+analyze_table_list:
+ analyze_table_elem_spec
+ | analyze_table_list ',' analyze_table_elem_spec
+ ;
+
+analyze_table_elem_spec:
+ table_name opt_persistent_stat_clause
+ ;
+
+opt_persistent_stat_clause:
+ /* empty */
+ {}
+ | PERSISTENT_SYM FOR_SYM persistent_stat_spec
+ {
+ thd->lex->with_persistent_for_clause= TRUE;
+ }
+ ;
+
+persistent_stat_spec:
+ ALL
+ {}
+ | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec
+ {}
+
+persistent_column_stat_spec:
+ ALL {}
+ | '('
+ {
+ LEX* lex= thd->lex;
+ lex->column_list= new (thd->mem_root) List<LEX_STRING>;
+ if (lex->column_list == NULL)
+ MYSQL_YYABORT;
+ }
+ table_column_list
+ ')'
+ ;
+
+persistent_index_stat_spec:
+ ALL {}
+ | '('
+ {
+ LEX* lex= thd->lex;
+ lex->index_list= new (thd->mem_root) List<LEX_STRING>;
+ if (lex->index_list == NULL)
+ MYSQL_YYABORT;
+ }
+ table_index_list
+ ')'
+ ;
+
+table_column_list:
+ /* empty */
+ {}
+ | ident
+ {
+ Lex->column_list->push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)), thd->mem_root);
+ }
+ | table_column_list ',' ident
+ {
+ Lex->column_list->push_back((LEX_STRING*)
+ thd->memdup(&$3, sizeof(LEX_STRING)), thd->mem_root);
+ }
+ ;
+
+table_index_list:
+ /* empty */
+ {}
+ | table_index_name
+ | table_index_list ',' table_index_name
+ ;
+
+table_index_name:
+ ident
+ {
+ Lex->index_list->push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ |
+ PRIMARY_SYM
+ {
+ LEX_STRING str= {(char*) "PRIMARY", 7};
+ Lex->index_list->push_back((LEX_STRING*)
+ thd->memdup(&str, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ ;
+
+binlog_base64_event:
+ BINLOG_SYM TEXT_STRING_sys
+ {
+ Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
+ Lex->comment= $2;
+ }
+ ;
+
+check_view_or_table:
+ table_or_tables table_list opt_mi_check_type
+ | VIEW_SYM
+ { Lex->table_type= TABLE_TYPE_VIEW; }
+ table_list opt_view_check_type
+ ;
+
+check: CHECK_SYM
+ {
+ LEX *lex=Lex;
+
+ lex->sql_command = SQLCOM_CHECK;
+ lex->check_opt.init();
+ lex->alter_info.reset();
+ /* Will be overridden during execution. */
+ YYPS->m_lock_type= TL_UNLOCK;
+ }
+ check_view_or_table
+ {
+ LEX* lex= thd->lex;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "CHECK"));
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_mi_check_type:
+ /* empty */ { Lex->check_opt.flags = T_MEDIUM; }
+ | mi_check_types {}
+ ;
+
+mi_check_types:
+ mi_check_type {}
+ | mi_check_type mi_check_types {}
+ ;
+
+mi_check_type:
+ QUICK { Lex->check_opt.flags|= T_QUICK; }
+ | FAST_SYM { Lex->check_opt.flags|= T_FAST; }
+ | MEDIUM_SYM { Lex->check_opt.flags|= T_MEDIUM; }
+ | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
+ | CHANGED { Lex->check_opt.flags|= T_CHECK_ONLY_CHANGED; }
+ | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; }
+ ;
+
+opt_view_check_type:
+ /* empty */ { }
+ | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; }
+ ;
+
+optimize:
+ OPTIMIZE opt_no_write_to_binlog table_or_tables
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_OPTIMIZE;
+ lex->no_write_to_binlog= $2;
+ lex->check_opt.init();
+ lex->alter_info.reset();
+ /* Will be overridden during execution. */
+ YYPS->m_lock_type= TL_UNLOCK;
+ }
+ table_list
+ {
+ LEX* lex= thd->lex;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_no_write_to_binlog:
+ /* empty */ { $$= 0; }
+ | NO_WRITE_TO_BINLOG { $$= 1; }
+ | LOCAL_SYM { $$= 1; }
+ ;
+
+rename:
+ RENAME table_or_tables
+ {
+ Lex->sql_command= SQLCOM_RENAME_TABLE;
+ }
+ table_to_table_list
+ {}
+ | RENAME USER_SYM clear_privileges rename_list
+ {
+ Lex->sql_command = SQLCOM_RENAME_USER;
+ }
+ ;
+
+rename_list:
+ user TO_SYM user
+ {
+ if (Lex->users_list.push_back($1, thd->mem_root) ||
+ Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | rename_list ',' user TO_SYM user
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root) ||
+ Lex->users_list.push_back($5, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+table_to_table_list:
+ table_to_table
+ | table_to_table_list ',' table_to_table
+ ;
+
+table_to_table:
+ table_ident TO_SYM table_ident
+ {
+ LEX *lex=Lex;
+ SELECT_LEX *sl= lex->current_select;
+ if (!sl->add_table_to_list(thd, $1,NULL,TL_OPTION_UPDATING,
+ TL_IGNORE, MDL_EXCLUSIVE) ||
+ !sl->add_table_to_list(thd, $3,NULL,TL_OPTION_UPDATING,
+ TL_IGNORE, MDL_EXCLUSIVE))
+ MYSQL_YYABORT;
+ }
+ ;
+
+keycache:
+ CACHE_SYM INDEX_SYM
+ {
+ Lex->alter_info.reset();
+ }
+ keycache_list_or_parts IN_SYM key_cache_name
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
+ lex->ident= $6;
+ }
+ ;
+
+keycache_list_or_parts:
+ keycache_list
+ | assign_to_keycache_parts
+ ;
+
+keycache_list:
+ assign_to_keycache
+ | keycache_list ',' assign_to_keycache
+ ;
+
+assign_to_keycache:
+ table_ident cache_keys_spec
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL, 0, TL_READ,
+ MDL_SHARED_READ,
+ Select->pop_index_hints()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+assign_to_keycache_parts:
+ table_ident adm_partition cache_keys_spec
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL, 0, TL_READ,
+ MDL_SHARED_READ,
+ Select->pop_index_hints()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+key_cache_name:
+ ident { $$= $1; }
+ | DEFAULT { $$ = default_key_cache_base; }
+ ;
+
+preload:
+ LOAD INDEX_SYM INTO CACHE_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_PRELOAD_KEYS;
+ lex->alter_info.reset();
+ }
+ preload_list_or_parts
+ {}
+ ;
+
+preload_list_or_parts:
+ preload_keys_parts
+ | preload_list
+ ;
+
+preload_list:
+ preload_keys
+ | preload_list ',' preload_keys
+ ;
+
+preload_keys:
+ table_ident cache_keys_spec opt_ignore_leaves
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL, $3, TL_READ,
+ MDL_SHARED_READ,
+ Select->pop_index_hints()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+preload_keys_parts:
+ table_ident adm_partition cache_keys_spec opt_ignore_leaves
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL, $4, TL_READ,
+ MDL_SHARED_READ,
+ Select->pop_index_hints()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+adm_partition:
+ PARTITION_SYM have_partitioning
+ {
+ Lex->alter_info.flags|= Alter_info::ALTER_ADMIN_PARTITION;
+ }
+ '(' all_or_alt_part_name_list ')'
+ ;
+
+cache_keys_spec:
+ {
+ Lex->select_lex.alloc_index_hints(thd);
+ Select->set_index_hint_type(INDEX_HINT_USE,
+ INDEX_HINT_MASK_ALL);
+ }
+ cache_key_list_or_empty
+ ;
+
+cache_key_list_or_empty:
+ /* empty */ { }
+ | key_or_index '(' opt_key_usage_list ')'
+ ;
+
+opt_ignore_leaves:
+ /* empty */
+ { $$= 0; }
+ | IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; }
+ ;
+
+/*
+ Select : retrieve data from table
+*/
+
+
+select:
+ opt_with_clause select_init
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->current_select->set_with_clause($1);
+ }
+ ;
+
+select_init:
+ SELECT_SYM select_options_and_item_list select_init3
+ | '(' select_paren ')'
+ | '(' select_paren ')' union_list
+ | '(' select_paren ')' union_order_or_limit
+ ;
+
+union_list_part2:
+ SELECT_SYM select_options_and_item_list select_init3_union_query_term
+ | '(' select_paren_union_query_term ')'
+ | '(' select_paren_union_query_term ')' union_list
+ | '(' select_paren_union_query_term ')' union_order_or_limit
+ ;
+
+select_paren:
+ {
+ /*
+ In order to correctly parse UNION's global ORDER BY we need to
+ set braces before parsing the clause.
+ */
+ Lex->current_select->set_braces(true);
+ }
+ SELECT_SYM select_options_and_item_list select_part3
+ opt_select_lock_type
+ {
+ DBUG_ASSERT(Lex->current_select->braces);
+ }
+ | '(' select_paren ')'
+ ;
+
+select_paren_union_query_term:
+ {
+ /*
+ In order to correctly parse UNION's global ORDER BY we need to
+ set braces before parsing the clause.
+ */
+ Lex->current_select->set_braces(true);
+ }
+ SELECT_SYM select_options_and_item_list select_part3_union_query_term
+ opt_select_lock_type
+ {
+ DBUG_ASSERT(Lex->current_select->braces);
+ }
+ | '(' select_paren_union_query_term ')'
+ ;
+
+select_paren_view:
+ {
+ /*
+ In order to correctly parse UNION's global ORDER BY we need to
+ set braces before parsing the clause.
+ */
+ Lex->current_select->set_braces(true);
+ }
+ SELECT_SYM select_options_and_item_list select_part3_view
+ opt_select_lock_type
+ {
+ DBUG_ASSERT(Lex->current_select->braces);
+ }
+ | '(' select_paren_view ')'
+ ;
+
+/* The equivalent of select_paren for nested queries. */
+select_paren_derived:
+ {
+ Lex->current_select->set_braces(true);
+ }
+ SELECT_SYM select_part2_derived
+ opt_table_expression
+ opt_order_clause
+ opt_limit_clause
+ opt_select_lock_type
+ {
+ DBUG_ASSERT(Lex->current_select->braces);
+ $$= Lex->current_select->master_unit()->first_select();
+ }
+ | '(' select_paren_derived ')' { $$= $2; }
+ ;
+
+select_init3:
+ opt_table_expression
+ opt_select_lock_type
+ {
+ /* Parentheses carry no meaning here */
+ Lex->current_select->set_braces(false);
+ }
+ union_clause
+ | select_part3_union_not_ready
+ opt_select_lock_type
+ {
+ /* Parentheses carry no meaning here */
+ Lex->current_select->set_braces(false);
+ }
+ ;
+
+
+select_init3_union_query_term:
+ opt_table_expression
+ opt_select_lock_type
+ {
+ /* Parentheses carry no meaning here */
+ Lex->current_select->set_braces(false);
+ }
+ union_clause
+ | select_part3_union_not_ready_noproc
+ opt_select_lock_type
+ {
+ /* Parentheses carry no meaning here */
+ Lex->current_select->set_braces(false);
+ }
+ ;
+
+
+select_init3_view:
+ opt_table_expression opt_select_lock_type
+ {
+ Lex->current_select->set_braces(false);
+ }
+ | opt_table_expression opt_select_lock_type
+ {
+ Lex->current_select->set_braces(false);
+ }
+ union_list_view
+ | order_or_limit opt_select_lock_type
+ {
+ Lex->current_select->set_braces(false);
+ }
+ | table_expression order_or_limit opt_select_lock_type
+ {
+ Lex->current_select->set_braces(false);
+ }
+ ;
+
+/*
+ The SELECT parts after select_item_list that cannot be followed by UNION.
+*/
+
+select_part3:
+ opt_table_expression
+ | select_part3_union_not_ready
+ ;
+
+select_part3_union_query_term:
+ opt_table_expression
+ | select_part3_union_not_ready_noproc
+ ;
+
+select_part3_view:
+ opt_table_expression
+ | order_or_limit
+ | table_expression order_or_limit
+ ;
+
+select_part3_union_not_ready:
+ select_part3_union_not_ready_noproc
+ | table_expression procedure_clause
+ | table_expression order_or_limit procedure_clause
+ ;
+
+select_part3_union_not_ready_noproc:
+ order_or_limit
+ | into opt_table_expression opt_order_clause opt_limit_clause
+ | table_expression into
+ | table_expression order_or_limit
+ | table_expression order_or_limit into
+ ;
+
+select_options_and_item_list:
+ {
+ LEX *lex= Lex;
+ SELECT_LEX *sel= lex->current_select;
+ if (sel->linkage != UNION_TYPE)
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ ;
+
+
+/**
+ <table expression>, as in the SQL standard.
+*/
+table_expression:
+ from_clause
+ opt_where_clause
+ opt_group_clause
+ opt_having_clause
+ opt_window_clause
+ ;
+
+opt_table_expression:
+ /* Empty */
+ | table_expression
+ ;
+
+from_clause:
+ FROM table_reference_list
+ ;
+
+table_reference_list:
+ join_table_list
+ {
+ Select->context.table_list=
+ Select->context.first_name_resolution_table=
+ Select->table_list.first;
+ }
+ | DUAL_SYM
+ /* oracle compatibility: oracle always requires FROM clause,
+ and DUAL is system table without fields.
+ Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ?
+ Hmmm :) */
+ ;
+
+select_options:
+ /* empty*/
+ | select_option_list
+ {
+ if (Select->options & SELECT_DISTINCT && Select->options & SELECT_ALL)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"));
+ }
+ ;
+
+select_option_list:
+ select_option_list select_option
+ | select_option
+ ;
+
+select_option:
+ query_expression_option
+ | SQL_NO_CACHE_SYM
+ {
+ /*
+ Allow this flag only on the first top-level SELECT statement, if
+ SQL_CACHE wasn't specified, and only once per query.
+ */
+ if (Lex->current_select != &Lex->select_lex)
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
+
+ Lex->safe_to_cache_query=0;
+ Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
+ }
+ | SQL_CACHE_SYM
+ {
+ /*
+ Allow this flag only on the first top-level SELECT statement, if
+ SQL_NO_CACHE wasn't specified, and only once per query.
+ */
+ if (Lex->current_select != &Lex->select_lex)
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
+
+ Lex->safe_to_cache_query=1;
+ Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
+ }
+ ;
+
+opt_select_lock_type:
+ /* empty */
+ | FOR_SYM UPDATE_SYM
+ {
+ LEX *lex=Lex;
+ lex->current_select->lock_type= TL_WRITE;
+ lex->current_select->set_lock_for_tables(TL_WRITE);
+ lex->safe_to_cache_query=0;
+ }
+ | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
+ {
+ LEX *lex=Lex;
+ lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
+ lex->current_select->
+ set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
+ lex->safe_to_cache_query=0;
+ }
+ ;
+
+select_item_list:
+ select_item_list ',' select_item
+ | select_item
+ | '*'
+ {
+ Item *item= new (thd->mem_root)
+ Item_field(thd, &thd->lex->current_select->context,
+ NULL, NULL, &star_clex_str);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ if (add_item_to_list(thd, item))
+ MYSQL_YYABORT;
+ (thd->lex->current_select->with_wild)++;
+ }
+ ;
+
+select_item:
+ remember_name table_wild remember_end
+ {
+ if (add_item_to_list(thd, $2))
+ MYSQL_YYABORT;
+ }
+ | remember_name expr remember_end select_alias
+ {
+ DBUG_ASSERT($1 < $3);
+
+ if (add_item_to_list(thd, $2))
+ MYSQL_YYABORT;
+ if ($4.str)
+ {
+ if (Lex->sql_command == SQLCOM_CREATE_VIEW &&
+ check_column_name($4.str))
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), $4.str));
+ $2->is_autogenerated_name= FALSE;
+ $2->set_name(thd, $4.str, $4.length, system_charset_info);
+ }
+ else if (!$2->name.str || $2->name.str == item_empty_name)
+ {
+ $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
+ }
+ }
+ ;
+
+colon_with_pos:
+ ':'
+ {
+ $$= (char *) YYLIP->get_tok_start();
+ }
+ ;
+
+remember_tok_start:
+ {
+ $$= (char*) YYLIP->get_tok_start();
+ }
+ ;
+
+remember_name:
+ {
+ $$= (char*) YYLIP->get_cpp_tok_start();
+ }
+ ;
+
+remember_end:
+ {
+ $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
+ }
+ ;
+
+select_alias:
+ /* empty */ { $$=null_clex_str;}
+ | AS ident { $$=$2; }
+ | AS TEXT_STRING_sys { $$=$2; }
+ | ident { $$=$1; }
+ | TEXT_STRING_sys { $$=$1; }
+ ;
+
+opt_default_time_precision:
+ /* empty */ { $$= NOT_FIXED_DEC; }
+ | '(' ')' { $$= NOT_FIXED_DEC; }
+ | '(' real_ulong_num ')' { $$= $2; };
+ ;
+
+opt_time_precision:
+ /* empty */ { $$= 0; }
+ | '(' ')' { $$= 0; }
+ | '(' real_ulong_num ')' { $$= $2; };
+ ;
+
+optional_braces:
+ /* empty */ {}
+ | '(' ')' {}
+ ;
+
+/* all possible expressions */
+expr:
+ expr or expr %prec OR_SYM
+ {
+ /*
+ Design notes:
+ Do not use a manually maintained stack like thd->lex->xxx_list,
+ but use the internal bison stack ($$, $1 and $3) instead.
+ Using the bison stack is:
+ - more robust to changes in the grammar,
+ - guaranteed to be in sync with the parser state,
+ - better for performances (no memory allocation).
+ */
+ Item_cond_or *item1;
+ Item_cond_or *item3;
+ if (is_cond_or($1))
+ {
+ item1= (Item_cond_or*) $1;
+ if (is_cond_or($3))
+ {
+ item3= (Item_cond_or*) $3;
+ /*
+ (X1 OR X2) OR (Y1 OR Y2) ==> OR (X1, X2, Y1, Y2)
+ */
+ item3->add_at_head(item1->argument_list());
+ $$ = $3;
+ }
+ else
+ {
+ /*
+ (X1 OR X2) OR Y ==> OR (X1, X2, Y)
+ */
+ item1->add($3, thd->mem_root);
+ $$ = $1;
+ }
+ }
+ else if (is_cond_or($3))
+ {
+ item3= (Item_cond_or*) $3;
+ /*
+ X OR (Y1 OR Y2) ==> OR (X, Y1, Y2)
+ */
+ item3->add_at_head($1, thd->mem_root);
+ $$ = $3;
+ }
+ else
+ {
+ /* X OR Y */
+ $$= new (thd->mem_root) Item_cond_or(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ }
+ | expr XOR expr %prec XOR
+ {
+ /* XOR is a proprietary extension */
+ $$= new (thd->mem_root) Item_func_xor(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | expr and expr %prec AND_SYM
+ {
+ /* See comments in rule expr: expr or expr */
+ Item_cond_and *item1;
+ Item_cond_and *item3;
+ if (is_cond_and($1))
+ {
+ item1= (Item_cond_and*) $1;
+ if (is_cond_and($3))
+ {
+ item3= (Item_cond_and*) $3;
+ /*
+ (X1 AND X2) AND (Y1 AND Y2) ==> AND (X1, X2, Y1, Y2)
+ */
+ item3->add_at_head(item1->argument_list());
+ $$ = $3;
+ }
+ else
+ {
+ /*
+ (X1 AND X2) AND Y ==> AND (X1, X2, Y)
+ */
+ item1->add($3, thd->mem_root);
+ $$ = $1;
+ }
+ }
+ else if (is_cond_and($3))
+ {
+ item3= (Item_cond_and*) $3;
+ /*
+ X AND (Y1 AND Y2) ==> AND (X, Y1, Y2)
+ */
+ item3->add_at_head($1, thd->mem_root);
+ $$ = $3;
+ }
+ else
+ {
+ /* X AND Y */
+ $$= new (thd->mem_root) Item_cond_and(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ }
+ | NOT_SYM expr %prec NOT_SYM
+ {
+ $$= negate_expression(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS TRUE_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_istrue(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS not TRUE_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isnottrue(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS FALSE_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isfalse(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS not FALSE_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isnotfalse(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS UNKNOWN_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isnull(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS not UNKNOWN_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri
+ ;
+
+bool_pri:
+ bool_pri IS NULL_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isnull(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri IS not NULL_SYM %prec IS
+ {
+ $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
+ {
+ $$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri comp_op predicate %prec '='
+ {
+ $$= (*$2)(0)->create(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bool_pri comp_op all_or_any '(' subselect ')' %prec '='
+ {
+ $$= all_any_subquery_creator(thd, $1, $2, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | predicate
+ ;
+
+predicate:
+ bit_expr IN_SYM '(' subselect ')'
+ {
+ $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr not IN_SYM '(' subselect ')'
+ {
+ Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= negate_expression(thd, item);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr IN_SYM '(' expr ')'
+ {
+ $$= handle_sql2003_note184_exception(thd, $1, true, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr IN_SYM '(' expr ',' expr_list ')'
+ {
+ $6->push_front($4, thd->mem_root);
+ $6->push_front($1, thd->mem_root);
+ $$= new (thd->mem_root) Item_func_in(thd, *$6);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr not IN_SYM '(' expr ')'
+ {
+ $$= handle_sql2003_note184_exception(thd, $1, false, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr not IN_SYM '(' expr ',' expr_list ')'
+ {
+ $7->push_front($5, thd->mem_root);
+ $7->push_front($1, thd->mem_root);
+ Item_func_in *item= new (thd->mem_root) Item_func_in(thd, *$7);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= item->neg_transformer(thd);
+ }
+ | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
+ {
+ $$= new (thd->mem_root) Item_func_between(thd, $1, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
+ {
+ Item_func_between *item;
+ item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= item->neg_transformer(thd);
+ }
+ | bit_expr SOUNDS_SYM LIKE bit_expr
+ {
+ Item *item1= new (thd->mem_root) Item_func_soundex(thd, $1);
+ Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4);
+ if ((item1 == NULL) || (item4 == NULL))
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_func_eq(thd, item1, item4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr LIKE simple_expr opt_escape
+ {
+ $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4,
+ Lex->escape_used);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr not LIKE simple_expr opt_escape
+ {
+ Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5,
+ Lex->escape_used);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= item->neg_transformer(thd);
+ }
+ | bit_expr REGEXP bit_expr
+ {
+ $$= new (thd->mem_root) Item_func_regex(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr not REGEXP bit_expr
+ {
+ Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= negate_expression(thd, item);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr
+ ;
+
+bit_expr:
+ bit_expr '|' bit_expr %prec '|'
+ {
+ $$= new (thd->mem_root) Item_func_bit_or(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '&' bit_expr %prec '&'
+ {
+ $$= new (thd->mem_root) Item_func_bit_and(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
+ {
+ $$= new (thd->mem_root) Item_func_shift_left(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT
+ {
+ $$= new (thd->mem_root) Item_func_shift_right(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '+' bit_expr %prec '+'
+ {
+ $$= new (thd->mem_root) Item_func_plus(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '-' bit_expr %prec '-'
+ {
+ $$= new (thd->mem_root) Item_func_minus(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '+' INTERVAL_SYM expr interval %prec '+'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '-' INTERVAL_SYM expr interval %prec '-'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $1, $4, $5, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '*' bit_expr %prec '*'
+ {
+ $$= new (thd->mem_root) Item_func_mul(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '/' bit_expr %prec '/'
+ {
+ $$= new (thd->mem_root) Item_func_div(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr DIV_SYM bit_expr %prec DIV_SYM
+ {
+ $$= new (thd->mem_root) Item_func_int_div(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr MOD_SYM bit_expr %prec MOD_SYM
+ {
+ $$= new (thd->mem_root) Item_func_mod(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | bit_expr '^' bit_expr
+ {
+ $$= new (thd->mem_root) Item_func_bit_xor(thd, $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | simple_expr
+ ;
+
+or:
+ OR_SYM
+ | OR2_SYM
+ ;
+
+and:
+ AND_SYM
+ | AND_AND_SYM
+ ;
+
+not:
+ NOT_SYM
+ | NOT2_SYM
+ ;
+
+not2:
+ '!'
+ | NOT2_SYM
+ ;
+
+comp_op:
+ '=' { $$ = &comp_eq_creator; }
+ | GE { $$ = &comp_ge_creator; }
+ | '>' { $$ = &comp_gt_creator; }
+ | LE { $$ = &comp_le_creator; }
+ | '<' { $$ = &comp_lt_creator; }
+ | NE { $$ = &comp_ne_creator; }
+ ;
+
+all_or_any:
+ ALL { $$ = 1; }
+ | ANY_SYM { $$ = 0; }
+ ;
+
+opt_dyncol_type:
+ /* empty */
+ {
+ $$.set(DYN_COL_NULL); /* automatic type */
+ Lex->charset= NULL;
+ }
+ | AS dyncol_type { $$= $2; }
+ ;
+
+dyncol_type:
+ numeric_dyncol_type { $$= $1; Lex->charset= NULL; }
+ | temporal_dyncol_type { $$= $1; Lex->charset= NULL; }
+ | string_dyncol_type { $$= $1; }
+ ;
+
+numeric_dyncol_type:
+ INT_SYM { $$.set(DYN_COL_INT); }
+ | UNSIGNED INT_SYM { $$.set(DYN_COL_UINT); }
+ | DOUBLE_SYM { $$.set(DYN_COL_DOUBLE); }
+ | REAL { $$.set(DYN_COL_DOUBLE); }
+ | FLOAT_SYM { $$.set(DYN_COL_DOUBLE); }
+ | DECIMAL_SYM float_options { $$.set(DYN_COL_DECIMAL, $2); }
+ ;
+
+temporal_dyncol_type:
+ DATE_SYM { $$.set(DYN_COL_DATE); }
+ | TIME_SYM opt_field_length { $$.set(DYN_COL_TIME, 0, $2); }
+ | DATETIME opt_field_length { $$.set(DYN_COL_DATETIME, 0, $2); }
+ ;
+
+string_dyncol_type:
+ char
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
+ {
+ $$.set(DYN_COL_STRING);
+ }
+ | nchar
+ {
+ $$.set(DYN_COL_STRING);
+ Lex->charset= national_charset_info;
+ }
+ ;
+
+dyncall_create_element:
+ expr ',' expr opt_dyncol_type
+ {
+ LEX *lex= Lex;
+ $$= (DYNCALL_CREATE_DEF *)
+ alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->key= $1;
+ $$->value= $3;
+ $$->type= (DYNAMIC_COLUMN_TYPE)$4.dyncol_type();
+ $$->cs= lex->charset;
+ if ($4.length())
+ $$->len= strtoul($4.length(), NULL, 10);
+ else
+ $$->len= 0;
+ if ($4.dec())
+ $$->frac= strtoul($4.dec(), NULL, 10);
+ else
+ $$->len= 0;
+ }
+
+dyncall_create_list:
+ dyncall_create_element
+ {
+ $$= new (thd->mem_root) List<DYNCALL_CREATE_DEF>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | dyncall_create_list ',' dyncall_create_element
+ {
+ $1->push_back($3, thd->mem_root);
+ $$= $1;
+ }
+ ;
+
+sp_cursor_name_and_offset:
+ ident
+ {
+ LEX *lex= Lex;
+ $$.name= $1;
+ if (!lex->spcont ||
+ !lex->spcont->find_cursor(&$1, &$$.offset, false))
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $1.str));
+ }
+ ;
+
+explicit_cursor_attr:
+ sp_cursor_name_and_offset '%' ISOPEN_SYM
+ {
+ if (!($$= new (thd->mem_root)
+ Item_func_cursor_isopen(thd, &$1.name, $1.offset)))
+ MYSQL_YYABORT;
+ }
+ | sp_cursor_name_and_offset '%' FOUND_SYM
+ {
+ if (!($$= new (thd->mem_root)
+ Item_func_cursor_found(thd, &$1.name, $1.offset)))
+ MYSQL_YYABORT;
+ }
+ | sp_cursor_name_and_offset '%' NOTFOUND_SYM
+ {
+ if (!($$= new (thd->mem_root)
+ Item_func_cursor_notfound(thd, &$1.name, $1.offset)))
+ MYSQL_YYABORT;
+ }
+ | sp_cursor_name_and_offset '%' ROWCOUNT_SYM
+ {
+ if (!($$= new (thd->mem_root)
+ Item_func_cursor_rowcount(thd, &$1.name, $1.offset)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/*
+ Expressions that the parser allows in a column DEFAULT clause
+ without parentheses. These expressions cannot end with a COLLATE clause.
+
+ If we allowed any "expr" in DEFAULT clause, there would be a confusion
+ in queries like this:
+ CREATE TABLE t1 (a TEXT DEFAULT 'a' COLLATE latin1_bin);
+ It would be not clear what COLLATE stands for:
+ - the collation of the column `a`, or
+ - the collation of the string literal 'a'
+
+ This restriction allows to parse the above query unambiguiusly:
+ COLLATE belongs to the column rather than the literal.
+ If one needs COLLATE to belong to the literal, parentheses must be used:
+ CREATE TABLE t1 (a TEXT DEFAULT ('a' COLLATE latin1_bin));
+ Note: the COLLATE clause is rather meaningless here, but the query
+ is syntactically correct.
+
+ Note, some of the expressions are not actually allowed in DEFAULT,
+ e.g. sum_expr, window_func_expr, ROW(...), VALUES().
+ We could move them to simple_expr, but that would make
+ these two queries return a different error messages:
+ CREATE TABLE t1 (a INT DEFAULT AVG(1));
+ CREATE TABLE t1 (a INT DEFAULT (AVG(1)));
+ The first query would return "syntax error".
+ Currenly both return:
+ Function or expression 'avg(' is not allowed for 'DEFAULT' ...
+*/
+column_default_non_parenthesized_expr:
+ simple_ident
+ | function_call_keyword
+ | function_call_nonkeyword
+ | function_call_generic
+ | function_call_conflict
+ | literal
+ | param_marker { $$= $1; }
+ | variable
+ | sum_expr
+ | window_func_expr
+ | ROW_SYM '(' expr ',' expr_list ')'
+ {
+ $5->push_front($3, thd->mem_root);
+ $$= new (thd->mem_root) Item_row(thd, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | EXISTS '(' subselect ')'
+ {
+ $$= new (thd->mem_root) Item_exists_subselect(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '{' ident expr '}'
+ {
+ $$= NULL;
+ /*
+ If "expr" is reasonably short pure ASCII string literal,
+ try to parse known ODBC style date, time or timestamp literals,
+ e.g:
+ SELECT {d'2001-01-01'};
+ SELECT {t'10:20:30'};
+ SELECT {ts'2001-01-01 10:20:30'};
+ */
+ if ($3->type() == Item::STRING_ITEM)
+ {
+ Item_string *item= (Item_string *) $3;
+ enum_field_types type= item->odbc_temporal_literal_type(&$2);
+ if (type != MYSQL_TYPE_STRING)
+ {
+ $$= create_temporal_literal(thd, item->val_str(NULL),
+ type, false);
+ }
+ }
+ if ($$ == NULL)
+ $$= $3;
+ }
+ | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
+ {
+ $2->push_front($5, thd->mem_root);
+ Item_func_match *i1= new (thd->mem_root) Item_func_match(thd, *$2,
+ $6);
+ if (i1 == NULL)
+ MYSQL_YYABORT;
+ Select->add_ftfunc_to_list(thd, i1);
+ $$= i1;
+ }
+ | CAST_SYM '(' expr AS cast_type ')'
+ {
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
+ MYSQL_YYABORT;
+ }
+ | CASE_SYM opt_expr when_list opt_else END
+ {
+ $$= new (thd->mem_root) Item_func_case(thd, *$3, $2, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CONVERT_SYM '(' expr ',' cast_type ')'
+ {
+ if (!($$= $5.create_typecast_item(thd, $3, Lex->charset)))
+ MYSQL_YYABORT;
+ }
+ | CONVERT_SYM '(' expr USING charset_name ')'
+ {
+ $$= new (thd->mem_root) Item_func_conv_charset(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DECODE_SYM '(' expr ',' decode_when_list ')'
+ {
+ if (($5->elements % 2) == 0)
+ {
+ // No default expression
+ $$= new (thd->mem_root) Item_func_case(thd, *$5, $3, NULL);
+ }
+ else
+ {
+ /*
+ There is a default expression at the end of the list $5.
+ Create a new list without the default expression.
+ */
+ List<Item> tmp;
+ List_iterator_fast<Item> it(*$5);
+ for (uint i= 0; i < $5->elements - 1; i++) // copy all but last
+ {
+ Item *item= it++;
+ tmp.push_back(item);
+ }
+ /*
+ Now the new list "tmp" contains only WHEN-THEN pairs,
+ The default expression is pointed by the iterator "it"
+ and will be returned by the next call for it++ below.
+ */
+ $$= new (thd->mem_root) Item_func_case(thd, tmp, $3, it++);
+ }
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DEFAULT '(' simple_ident ')'
+ {
+ Item_splocal *il= $3->get_item_splocal();
+ if (il)
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str));
+ $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(),
+ $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | VALUES '(' simple_ident_nospvar ')'
+ {
+ $$= new (thd->mem_root) Item_insert_value(thd, Lex->current_context(),
+ $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | NEXT_SYM VALUE_SYM FOR_SYM table_ident
+ {
+ if (!($$= Lex->create_item_func_nextval(thd, $4)))
+ MYSQL_YYABORT;
+ }
+ | NEXTVAL_SYM '(' table_ident ')'
+ {
+ if (!($$= Lex->create_item_func_nextval(thd, $3)))
+ MYSQL_YYABORT;
+ }
+ | PREVIOUS_SYM VALUE_SYM FOR_SYM table_ident
+ {
+ if (!($$= Lex->create_item_func_lastval(thd, $4)))
+ MYSQL_YYABORT;
+ }
+ | LASTVAL_SYM '(' table_ident ')'
+ {
+ if (!($$= Lex->create_item_func_lastval(thd, $3)))
+ MYSQL_YYABORT;
+ }
+ | SETVAL_SYM '(' table_ident ',' longlong_num ')'
+ {
+ if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, 1)))
+ MYSQL_YYABORT;
+ }
+ | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ')'
+ {
+ if (!($$= Lex->create_item_func_setval(thd, $3, $5, 0, $7)))
+ MYSQL_YYABORT;
+ }
+ | SETVAL_SYM '(' table_ident ',' longlong_num ',' bool ',' ulonglong_num ')'
+ {
+ if (!($$= Lex->create_item_func_setval(thd, $3, $5, $9, $7)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+simple_expr:
+ column_default_non_parenthesized_expr
+ | explicit_cursor_attr
+ | simple_expr COLLATE_SYM ident_or_text %prec NEG
+ {
+ Item *i1= new (thd->mem_root) Item_string(thd, $3.str,
+ $3.length,
+ thd->charset());
+ if (i1 == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_func_set_collation(thd, $1, i1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '(' parenthesized_expr ')' { $$= $2; }
+ | BINARY simple_expr %prec NEG
+ {
+ Type_cast_attributes at(&my_charset_bin);
+ if (!($$= type_handler_long_blob.create_typecast_item(thd, $2, at)))
+ MYSQL_YYABORT;
+ }
+ | simple_expr OR_OR_SYM simple_expr
+ {
+ $$= new (thd->mem_root) Item_func_concat_operator_oracle(thd,
+ $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '+' simple_expr %prec NEG
+ {
+ $$= $2;
+ }
+ | '-' simple_expr %prec NEG
+ {
+ $$= $2->neg(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '~' simple_expr %prec NEG
+ {
+ $$= new (thd->mem_root) Item_func_bit_neg(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | not2 simple_expr %prec NEG
+ {
+ $$= negate_expression(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM
+ /* we cannot put interval before - */
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $5, $2, $3, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+/*
+ Function call syntax using official SQL 2003 keywords.
+ Because the function name is an official token,
+ a dedicated grammar rule is needed in the parser.
+ There is no potential for conflicts
+*/
+function_call_keyword:
+ CHAR_SYM '(' expr_list ')'
+ {
+ $$= new (thd->mem_root) Item_func_char(thd, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CHAR_SYM '(' expr_list USING charset_name ')'
+ {
+ $$= new (thd->mem_root) Item_func_char(thd, *$3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CURRENT_USER optional_braces
+ {
+ $$= new (thd->mem_root) Item_func_current_user(thd,
+ Lex->current_context());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query= 0;
+ }
+ | CURRENT_ROLE optional_braces
+ {
+ $$= new (thd->mem_root) Item_func_current_role(thd,
+ Lex->current_context());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query= 0;
+ }
+ | DATE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_date_typecast(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DAY_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_dayofmonth(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | HOUR_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_hour(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | INSERT '(' expr ',' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_insert(thd, $3, $5, $7, $9);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | INTERVAL_SYM '(' expr ',' expr ')' %prec INTERVAL_SYM
+ {
+ List<Item> *list= new (thd->mem_root) List<Item>;
+ if (list == NULL)
+ MYSQL_YYABORT;
+ list->push_front($5, thd->mem_root);
+ list->push_front($3, thd->mem_root);
+ Item_row *item= new (thd->mem_root) Item_row(thd, *list);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_func_interval(thd, item);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | INTERVAL_SYM '(' expr ',' expr ',' expr_list ')' %prec INTERVAL_SYM
+ {
+ $7->push_front($5, thd->mem_root);
+ $7->push_front($3, thd->mem_root);
+ Item_row *item= new (thd->mem_root) Item_row(thd, *$7);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_func_interval(thd, item);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | LEFT '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_left(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MINUTE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_minute(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MONTH_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_month(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | RIGHT '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_right(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SECOND_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_second(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SQL_SYM '%' ROWCOUNT_SYM
+ {
+ $$= new (thd->mem_root) Item_func_oracle_sql_rowcount(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query= 0;
+ }
+ | TIME_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_time_typecast(thd, $3,
+ AUTO_SEC_PART_DIGITS);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TIMESTAMP '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_datetime_typecast(thd, $3,
+ AUTO_SEC_PART_DIGITS);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TIMESTAMP '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_add_time(thd, $3, $5, 1, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_trim(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' LEADING expr FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_ltrim(thd, $6, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' TRAILING expr FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_rtrim(thd, $6, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' BOTH expr FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_trim(thd, $6, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' LEADING FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_ltrim(thd, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' TRAILING FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_rtrim(thd, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' BOTH FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_trim(thd, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRIM '(' expr FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_trim(thd, $5, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | USER_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_func_user(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query=0;
+ }
+ | YEAR_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_year(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+/*
+ Function calls using non reserved keywords, with special syntaxic forms.
+ Dedicated grammar rules are needed because of the syntax,
+ but also have the potential to cause incompatibilities with other
+ parts of the language.
+ MAINTAINER:
+ The only reasons a function should be added here are:
+ - for compatibility reasons with another SQL syntax (CURDATE),
+ - for typing reasons (GET_FORMAT)
+ Any other 'Syntaxic sugar' enhancements should be *STRONGLY*
+ discouraged.
+*/
+function_call_nonkeyword:
+ ADDDATE_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5,
+ INTERVAL_DAY, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CURDATE optional_braces
+ {
+ $$= new (thd->mem_root) Item_func_curdate_local(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | CURTIME opt_time_precision
+ {
+ $$= new (thd->mem_root) Item_func_curtime_local(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
+ %prec INTERVAL_SYM
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
+ %prec INTERVAL_SYM
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | EXTRACT_SYM '(' interval FROM expr ')'
+ {
+ $$=new (thd->mem_root) Item_extract(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | GET_FORMAT '(' date_time_type ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_get_format(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | NOW_SYM opt_time_precision
+ {
+ $$= new (thd->mem_root) Item_func_now_local(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | POSITION_SYM '(' bit_expr IN_SYM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_locate(thd, $5, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUBDATE_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $5,
+ INTERVAL_DAY, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $3, $6, $7, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUBSTRING '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUBSTRING '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUBSTRING '(' expr FROM expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SYSDATE opt_time_precision
+ {
+ /*
+ Unlike other time-related functions, SYSDATE() is
+ replication-unsafe because it is not affected by the
+ TIMESTAMP variable. It is unsafe even if
+ sysdate_is_now=1, because the slave may have
+ sysdate_is_now=0.
+ */
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ if (global_system_variables.sysdate_is_now == 0)
+ $$= new (thd->mem_root) Item_func_sysdate_local(thd, $2);
+ else
+ $$= new (thd->mem_root) Item_func_now_local(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_date_add_interval(thd, $7, $5, $3, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_timestamp_diff(thd, $5, $7, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | UTC_DATE_SYM optional_braces
+ {
+ $$= new (thd->mem_root) Item_func_curdate_utc(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | UTC_TIME_SYM opt_time_precision
+ {
+ $$= new (thd->mem_root) Item_func_curtime_utc(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | UTC_TIMESTAMP_SYM opt_time_precision
+ {
+ $$= new (thd->mem_root) Item_func_now_utc(thd, $2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ |
+ COLUMN_ADD_SYM '(' expr ',' dyncall_create_list ')'
+ {
+ $$= create_func_dyncol_add(thd, $3, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_DELETE_SYM '(' expr ',' expr_list ')'
+ {
+ $$= create_func_dyncol_delete(thd, $3, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_CHECK_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_dyncol_check(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_CREATE_SYM '(' dyncall_create_list ')'
+ {
+ $$= create_func_dyncol_create(thd, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
+ {
+ LEX *lex= Lex;
+ $$= create_func_dyncol_get(thd, $3, $5, $7.type_handler(),
+ $7.length(), $7.dec(),
+ lex->charset);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+/*
+ Functions calls using a non reserved keyword, and using a regular syntax.
+ Because the non reserved keyword is used in another part of the grammar,
+ a dedicated rule is needed here.
+*/
+function_call_conflict:
+ ASCII_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_ascii(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CHARSET '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_charset(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | COALESCE '(' expr_list ')'
+ {
+ $$= new (thd->mem_root) Item_func_coalesce(thd, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | COLLATION_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_collation(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DATABASE '(' ')'
+ {
+ $$= new (thd->mem_root) Item_func_database(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->safe_to_cache_query=0;
+ }
+ | IF_SYM '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_if(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | FORMAT_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_format(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | FORMAT_SYM '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_format(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ /* LAST_VALUE here conflicts with the definition for window functions.
+ We have these 2 separate rules to remove the shift/reduce conflict.
+ */
+ | LAST_VALUE '(' expr ')'
+ {
+ List<Item> *list= new (thd->mem_root) List<Item>;
+ if (list == NULL)
+ MYSQL_YYABORT;
+ list->push_back($3, thd->mem_root);
+
+ $$= new (thd->mem_root) Item_func_last_value(thd, *list);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | LAST_VALUE '(' expr_list ',' expr ')'
+ {
+ $3->push_back($5, thd->mem_root);
+ $$= new (thd->mem_root) Item_func_last_value(thd, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MICROSECOND_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_microsecond(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MOD_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_mod(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | OLD_PASSWORD_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root)
+ Item_func_password(thd, $3, Item_func_password::OLD);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | PASSWORD_SYM '(' expr ')'
+ {
+ Item* i1;
+ i1= new (thd->mem_root) Item_func_password(thd, $3);
+ if (i1 == NULL)
+ MYSQL_YYABORT;
+ $$= i1;
+ }
+ | QUARTER_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_quarter(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | REPEAT_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_repeat(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | REPLACE '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | REVERSE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_reverse(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ROW_COUNT_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_func_row_count(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
+ Lex->safe_to_cache_query= 0;
+ }
+ | TRUNCATE_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_round(thd, $3, $5, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEEK_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_week(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEEK_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_week(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr opt_ws_levels ')'
+ {
+ $$= new (thd->mem_root) Item_func_weight_string(thd, $3, 0, 0, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr AS CHAR_SYM ws_nweights opt_ws_levels ')'
+ {
+ $$= new (thd->mem_root)
+ Item_func_weight_string(thd, $3, 0, $6,
+ $7 | MY_STRXFRM_PAD_WITH_SPACE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr AS BINARY ws_nweights ')'
+ {
+ Item *item= new (thd->mem_root) Item_char_typecast(thd, $3, $6,
+ &my_charset_bin);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root)
+ Item_func_weight_string(thd, item, 0, $6,
+ MY_STRXFRM_PAD_WITH_SPACE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | WEIGHT_STRING_SYM '(' expr ',' ulong_num ',' ulong_num ',' ulong_num ')'
+ {
+ $$= new (thd->mem_root) Item_func_weight_string(thd, $3, $5, $7,
+ $9);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | geometry_function
+ {
+#ifdef HAVE_SPATIAL
+ $$= $1;
+ /* $1 may be NULL, GEOM_NEW not tested for out of memory */
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+#else
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
+#endif
+ }
+ ;
+
+geometry_function:
+ CONTAINS_SYM '(' expr ',' expr ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_precise_rel(thd, $3, $5,
+ Item_func::SP_CONTAINS_FUNC));
+ }
+ | GEOMETRYCOLLECTION '(' expr_list ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_collection(thd, *$3,
+ Geometry::wkb_geometrycollection,
+ Geometry::wkb_point));
+ }
+ | LINESTRING '(' expr_list ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_collection(thd, *$3,
+ Geometry::wkb_linestring,
+ Geometry::wkb_point));
+ }
+ | MULTILINESTRING '(' expr_list ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_collection(thd, *$3,
+ Geometry::wkb_multilinestring,
+ Geometry::wkb_linestring));
+ }
+ | MULTIPOINT '(' expr_list ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_collection(thd, *$3,
+ Geometry::wkb_multipoint,
+ Geometry::wkb_point));
+ }
+ | MULTIPOLYGON '(' expr_list ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_collection(thd, *$3,
+ Geometry::wkb_multipolygon,
+ Geometry::wkb_polygon));
+ }
+ | POINT_SYM '(' expr ',' expr ')'
+ {
+ $$= GEOM_NEW(thd, Item_func_point(thd, $3, $5));
+ }
+ | POLYGON '(' expr_list ')'
+ {
+ $$= GEOM_NEW(thd,
+ Item_func_spatial_collection(thd, *$3,
+ Geometry::wkb_polygon,
+ Geometry::wkb_linestring));
+ }
+ ;
+
+/*
+ Regular function calls.
+ The function name is *not* a token, and therefore is guaranteed to not
+ introduce side effects to the language in general.
+ MAINTAINER:
+ All the new functions implemented for new features should fit into
+ this category. The place to implement the function itself is
+ in sql/item_create.cc
+*/
+function_call_generic:
+ IDENT_sys '('
+ {
+#ifdef HAVE_DLOPEN
+ udf_func *udf= 0;
+ LEX *lex= Lex;
+ if (using_udf_functions &&
+ (udf= find_udf($1.str, $1.length)) &&
+ udf->type == UDFTYPE_AGGREGATE)
+ {
+ if (lex->current_select->inc_in_sum_expr())
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ /* Temporary placing the result of find_udf in $3 */
+ $<udf>$= udf;
+#endif
+ }
+ opt_udf_expr_list ')'
+ {
+ Create_func *builder;
+ Item *item= NULL;
+
+ if (check_routine_name(&$1))
+ {
+ MYSQL_YYABORT;
+ }
+
+ /*
+ Implementation note:
+ names are resolved with the following order:
+ - MySQL native functions,
+ - User Defined Functions,
+ - Stored Functions (assuming the current <use> database)
+
+ This will be revised with WL#2128 (SQL PATH)
+ */
+ builder= find_native_function_builder(thd, &$1);
+ if (builder)
+ {
+ item= builder->create_func(thd, &$1, $4);
+ }
+ else
+ {
+#ifdef HAVE_DLOPEN
+ /* Retrieving the result of find_udf */
+ udf_func *udf= $<udf>3;
+
+ if (udf)
+ {
+ if (udf->type == UDFTYPE_AGGREGATE)
+ {
+ Select->in_sum_expr--;
+ }
+
+ item= Create_udf_func::s_singleton.create(thd, udf, $4);
+ }
+ else
+#endif
+ {
+ builder= find_qualified_function_builder(thd);
+ DBUG_ASSERT(builder);
+ item= builder->create_func(thd, &$1, $4);
+ }
+ }
+
+ if (! ($$= item))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ | ident '.' ident '(' opt_expr_list ')'
+ {
+ Create_qfunc *builder;
+ Item *item= NULL;
+
+ /*
+ The following in practice calls:
+ <code>Create_sp_func::create()</code>
+ and builds a stored function.
+
+ However, it's important to maintain the interface between the
+ parser and the implementation in item_create.cc clean,
+ since this will change with WL#2128 (SQL PATH):
+ - INFORMATION_SCHEMA.version() is the SQL 99 syntax for the native
+ function version(),
+ - MySQL.version() is the SQL 2003 syntax for the native function
+ version() (a vendor can specify any schema).
+ */
+
+ if (!$1.str || check_db_name((LEX_STRING*) &$1))
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
+ if (check_routine_name(&$3))
+ {
+ MYSQL_YYABORT;
+ }
+
+ builder= find_qualified_function_builder(thd);
+ DBUG_ASSERT(builder);
+ item= builder->create_with_db(thd, &$1, &$3, true, $5);
+
+ if (! ($$= item))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+fulltext_options:
+ opt_natural_language_mode opt_query_expansion
+ { $$= $1 | $2; }
+ | IN_SYM BOOLEAN_SYM MODE_SYM
+ { $$= FT_BOOL; }
+ ;
+
+opt_natural_language_mode:
+ /* nothing */ { $$= FT_NL; }
+ | IN_SYM NATURAL LANGUAGE_SYM MODE_SYM { $$= FT_NL; }
+ ;
+
+opt_query_expansion:
+ /* nothing */ { $$= 0; }
+ | WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; }
+ ;
+
+opt_udf_expr_list:
+ /* empty */ { $$= NULL; }
+ | udf_expr_list { $$= $1; }
+ ;
+
+udf_expr_list:
+ udf_expr
+ {
+ $$= new (thd->mem_root) List<Item>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | udf_expr_list ',' udf_expr
+ {
+ $1->push_back($3, thd->mem_root);
+ $$= $1;
+ }
+ ;
+
+udf_expr:
+ remember_name expr remember_end select_alias
+ {
+ /*
+ Use Item::name as a storage for the attribute value of user
+ defined function argument. It is safe to use Item::name
+ because the syntax will not allow having an explicit name here.
+ See WL#1017 re. udf attributes.
+ */
+ if ($4.str)
+ {
+ $2->is_autogenerated_name= FALSE;
+ $2->set_name(thd, $4.str, $4.length, system_charset_info);
+ }
+ /*
+ A field has to have its proper name in order for name
+ resolution to work, something we are only guaranteed if we
+ parse it out. If we hijack the input stream with
+ remember_name we may get quoted or escaped names.
+ */
+ else if ($2->type() != Item::FIELD_ITEM &&
+ $2->type() != Item::REF_ITEM /* For HAVING */ )
+ $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
+ $$= $2;
+ }
+ ;
+
+sum_expr:
+ AVG_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_avg(thd, $3, FALSE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | AVG_SYM '(' DISTINCT in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_avg(thd, $4, TRUE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | BIT_AND '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_and(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | BIT_OR '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_or(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | BIT_XOR '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_xor(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | COUNT_SYM '(' opt_all '*' ')'
+ {
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) 0L, 1);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_sum_count(thd, item);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | COUNT_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_count(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | COUNT_SYM '(' DISTINCT
+ { Select->in_sum_expr++; }
+ expr_list
+ { Select->in_sum_expr--; }
+ ')'
+ {
+ $$= new (thd->mem_root) Item_sum_count(thd, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MIN_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_min(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ /*
+ According to ANSI SQL, DISTINCT is allowed and has
+ no sense inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...)
+ is processed like an ordinary MIN | MAX()
+ */
+ | MIN_SYM '(' DISTINCT in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_min(thd, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MAX_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_max(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | MAX_SYM '(' DISTINCT in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_max(thd, $4);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | STD_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_std(thd, $3, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | VARIANCE_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_variance(thd, $3, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | STDDEV_SAMP_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_std(thd, $3, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | VAR_SAMP_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_variance(thd, $3, 1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUM_SYM '(' in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_sum(thd, $3, FALSE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SUM_SYM '(' DISTINCT in_sum_expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_sum(thd, $4, TRUE);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | GROUP_CONCAT_SYM '(' opt_distinct
+ { Select->in_sum_expr++; }
+ expr_list opt_gorder_clause
+ opt_gconcat_separator
+ ')'
+ {
+ SELECT_LEX *sel= Select;
+ sel->in_sum_expr--;
+ $$= new (thd->mem_root)
+ Item_func_group_concat(thd, Lex->current_context(), $3, $5,
+ sel->gorder_list, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $5->empty();
+ sel->gorder_list.empty();
+ }
+ ;
+
+window_func_expr:
+ window_func OVER_SYM window_name
+ {
+ $$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ if (Select->add_window_func((Item_window_func *) $$))
+ MYSQL_YYABORT;
+ }
+ |
+ window_func OVER_SYM window_spec
+ {
+ LEX *lex= Lex;
+ if (Select->add_window_spec(thd, lex->win_ref,
+ Select->group_list,
+ Select->order_list,
+ lex->win_frame))
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1,
+ thd->lex->win_spec);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ if (Select->add_window_func((Item_window_func *) $$))
+ MYSQL_YYABORT;
+ }
+ ;
+
+window_func:
+ simple_window_func
+ |
+ sum_expr
+ {
+ ((Item_sum *) $1)->mark_as_window_func_sum_expr();
+ }
+ ;
+
+simple_window_func:
+ ROW_NUMBER_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_sum_row_number(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ RANK_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_sum_rank(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ DENSE_RANK_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_sum_dense_rank(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ PERCENT_RANK_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_sum_percent_rank(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ CUME_DIST_SYM '(' ')'
+ {
+ $$= new (thd->mem_root) Item_sum_cume_dist(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ NTILE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_ntile(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ FIRST_VALUE_SYM '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_first_value(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ LAST_VALUE '(' expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_last_value(thd, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ NTH_VALUE_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_nth_value(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ LEAD_SYM '(' expr ')'
+ {
+ /* No second argument defaults to 1. */
+ Item* item_offset= new (thd->mem_root) Item_uint(thd, 1);
+ if (item_offset == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_sum_lead(thd, $3, item_offset);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ LEAD_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_lead(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ LAG_SYM '(' expr ')'
+ {
+ /* No second argument defaults to 1. */
+ Item* item_offset= new (thd->mem_root) Item_uint(thd, 1);
+ if (item_offset == NULL)
+ MYSQL_YYABORT;
+ $$= new (thd->mem_root) Item_sum_lag(thd, $3, item_offset);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ LAG_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_sum_lag(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+window_name:
+ ident
+ {
+ $$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+variable:
+ '@'
+ {
+ if (! Lex->parsing_options.allows_variable)
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
+ }
+ variable_aux
+ {
+ $$= $3;
+ }
+ ;
+
+variable_aux:
+ ident_or_text SET_VAR expr
+ {
+ Item_func_set_user_var *item;
+ $$= item= new (thd->mem_root) Item_func_set_user_var(thd, &$1, $3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ lex->set_var_list.push_back(item, thd->mem_root);
+ }
+ | ident_or_text
+ {
+ $$= new (thd->mem_root) Item_func_get_user_var(thd, &$1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ }
+ | '@' opt_var_ident_type ident_or_text opt_component
+ {
+ /* disallow "SELECT @@global.global.variable" */
+ if ($3.str && $4.str && check_reserved_words(&$3))
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ if (!($$= get_system_var(thd, $2, $3, $4)))
+ MYSQL_YYABORT;
+ if (!((Item_func_get_system_var*) $$)->is_written_to_binlog())
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
+ }
+ ;
+
+opt_distinct:
+ /* empty */ { $$ = 0; }
+ | DISTINCT { $$ = 1; }
+ ;
+
+opt_gconcat_separator:
+ /* empty */
+ {
+ $$= new (thd->mem_root) String(",", 1, &my_charset_latin1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | SEPARATOR_SYM text_string { $$ = $2; }
+ ;
+
+opt_gorder_clause:
+ /* empty */
+ | ORDER_SYM BY gorder_list;
+ ;
+
+gorder_list:
+ gorder_list ',' order_ident order_dir
+ { if (add_gorder_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
+ | order_ident order_dir
+ { if (add_gorder_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
+ ;
+
+in_sum_expr:
+ opt_all
+ {
+ LEX *lex= Lex;
+ if (lex->current_select->inc_in_sum_expr())
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ expr
+ {
+ Select->in_sum_expr--;
+ $$= $3;
+ }
+ ;
+
+cast_type:
+ BINARY opt_field_length
+ { $$.set(&type_handler_long_blob, $2); Lex->charset= &my_charset_bin; }
+ | CHAR_SYM opt_field_length
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
+ { $$.set(&type_handler_long_blob, $2); }
+ | VARCHAR field_length
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
+ { $$.set(&type_handler_long_blob, $2); }
+ | VARCHAR2 field_length
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
+ { $$.set(&type_handler_long_blob, $2); }
+ | NCHAR_SYM opt_field_length
+ {
+ Lex->charset= national_charset_info;
+ $$.set(&type_handler_long_blob, $2, 0);
+ }
+ | cast_type_numeric { $$= $1; Lex->charset= NULL; }
+ | cast_type_temporal { $$= $1; Lex->charset= NULL; }
+ ;
+
+cast_type_numeric:
+ INT_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM { $$.set(&type_handler_longlong); }
+ | SIGNED_SYM INT_SYM { $$.set(&type_handler_longlong); }
+ | UNSIGNED { $$.set(&type_handler_ulonglong); }
+ | UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
+ | DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
+ | DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
+ ;
+
+cast_type_temporal:
+ DATE_SYM { $$.set(&type_handler_newdate); }
+ | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); }
+ | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); }
+ ;
+
+opt_expr_list:
+ /* empty */ { $$= NULL; }
+ | expr_list { $$= $1;}
+ ;
+
+expr_list:
+ expr
+ {
+ $$= new (thd->mem_root) List<Item>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | expr_list ',' expr
+ {
+ $1->push_back($3, thd->mem_root);
+ $$= $1;
+ }
+ ;
+
+ident_list_arg:
+ ident_list { $$= $1; }
+ | '(' ident_list ')' { $$= $2; }
+ ;
+
+ident_list:
+ simple_ident
+ {
+ $$= new (thd->mem_root) List<Item>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | ident_list ',' simple_ident
+ {
+ $1->push_back($3, thd->mem_root);
+ $$= $1;
+ }
+ ;
+
+opt_expr:
+ /* empty */ { $$= NULL; }
+ | expr { $$= $1; }
+ ;
+
+opt_else:
+ /* empty */ { $$= NULL; }
+ | ELSE expr { $$= $2; }
+ ;
+
+when_list:
+ WHEN_SYM expr THEN_SYM expr
+ {
+ $$= new (thd->mem_root) List<Item>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($2, thd->mem_root);
+ $$->push_back($4, thd->mem_root);
+ }
+ | when_list WHEN_SYM expr THEN_SYM expr
+ {
+ $1->push_back($3, thd->mem_root);
+ $1->push_back($5, thd->mem_root);
+ $$= $1;
+ }
+ ;
+
+
+decode_when_list:
+ expr ',' expr
+ {
+ $$= new (thd->mem_root) List<Item>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ $$->push_back($3, thd->mem_root);
+ }
+ | decode_when_list ',' expr
+ {
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+
+/* Equivalent to <table reference> in the SQL:2003 standard. */
+/* Warning - may return NULL in case of incomplete SELECT */
+table_ref:
+ table_factor { $$= $1; }
+ | join_table
+ {
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->nest_last_join(thd)))
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+join_table_list:
+ derived_table_list { MYSQL_YYABORT_UNLESS($$=$1); }
+ ;
+
+/*
+ The ODBC escape syntax for Outer Join is: '{' OJ join_table '}'
+ The parser does not define OJ as a token, any ident is accepted
+ instead in $2 (ident). Also, all productions from table_ref can
+ be escaped, not only join_table. Both syntax extensions are safe
+ and are ignored.
+*/
+esc_table_ref:
+ table_ref { $$=$1; }
+ | '{' ident table_ref '}' { $$=$3; }
+ ;
+
+/* Equivalent to <table reference list> in the SQL:2003 standard. */
+/* Warning - may return NULL in case of incomplete SELECT */
+derived_table_list:
+ esc_table_ref { $$=$1; }
+ | derived_table_list ',' esc_table_ref
+ {
+ MYSQL_YYABORT_UNLESS($1 && ($$=$3));
+ }
+ ;
+
+/*
+ Notice that JOIN is a left-associative operation, and it must be parsed
+ as such, that is, the parser must process first the left join operand
+ then the right one. Such order of processing ensures that the parser
+ produces correct join trees which is essential for semantic analysis
+ and subsequent optimization phases.
+*/
+join_table:
+ /* INNER JOIN variants */
+ /*
+ Use %prec to evaluate production 'table_ref' before 'normal_join'
+ so that [INNER | CROSS] JOIN is properly nested as other
+ left-associative joins.
+ */
+ table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
+ { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; }
+ | table_ref normal_join table_ref
+ ON
+ {
+ MYSQL_YYABORT_UNLESS($1 && $3);
+ /* Change the current name resolution context to a local context. */
+ if (push_new_name_resolution_context(thd, $1, $3))
+ MYSQL_YYABORT;
+ Select->parsing_place= IN_ON;
+ }
+ expr
+ {
+ $3->straight=$2;
+ add_join_on(thd, $3, $6);
+ Lex->pop_context();
+ Select->parsing_place= NO_MATTER;
+ }
+ | table_ref normal_join table_ref
+ USING
+ {
+ MYSQL_YYABORT_UNLESS($1 && $3);
+ }
+ '(' using_list ')'
+ {
+ $3->straight=$2;
+ add_join_natural($1,$3,$7,Select);
+ $$=$3;
+ }
+ | table_ref NATURAL inner_join table_factor
+ {
+ MYSQL_YYABORT_UNLESS($1 && ($$=$4));
+ $4->straight=$3;
+ add_join_natural($1,$4,NULL,Select);
+ }
+
+ /* LEFT JOIN variants */
+ | table_ref LEFT opt_outer JOIN_SYM table_ref
+ ON
+ {
+ MYSQL_YYABORT_UNLESS($1 && $5);
+ /* Change the current name resolution context to a local context. */
+ if (push_new_name_resolution_context(thd, $1, $5))
+ MYSQL_YYABORT;
+ Select->parsing_place= IN_ON;
+ }
+ expr
+ {
+ add_join_on(thd, $5, $8);
+ Lex->pop_context();
+ $5->outer_join|=JOIN_TYPE_LEFT;
+ $$=$5;
+ Select->parsing_place= NO_MATTER;
+ }
+ | table_ref LEFT opt_outer JOIN_SYM table_factor
+ {
+ MYSQL_YYABORT_UNLESS($1 && $5);
+ }
+ USING '(' using_list ')'
+ {
+ add_join_natural($1,$5,$9,Select);
+ $5->outer_join|=JOIN_TYPE_LEFT;
+ $$=$5;
+ }
+ | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
+ {
+ MYSQL_YYABORT_UNLESS($1 && $6);
+ add_join_natural($1,$6,NULL,Select);
+ $6->outer_join|=JOIN_TYPE_LEFT;
+ $$=$6;
+ }
+
+ /* RIGHT JOIN variants */
+ | table_ref RIGHT opt_outer JOIN_SYM table_ref
+ ON
+ {
+ MYSQL_YYABORT_UNLESS($1 && $5);
+ /* Change the current name resolution context to a local context. */
+ if (push_new_name_resolution_context(thd, $1, $5))
+ MYSQL_YYABORT;
+ Select->parsing_place= IN_ON;
+ }
+ expr
+ {
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->convert_right_join()))
+ MYSQL_YYABORT;
+ add_join_on(thd, $$, $8);
+ Lex->pop_context();
+ Select->parsing_place= NO_MATTER;
+ }
+ | table_ref RIGHT opt_outer JOIN_SYM table_factor
+ {
+ MYSQL_YYABORT_UNLESS($1 && $5);
+ }
+ USING '(' using_list ')'
+ {
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->convert_right_join()))
+ MYSQL_YYABORT;
+ add_join_natural($$,$5,$9,Select);
+ }
+ | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
+ {
+ MYSQL_YYABORT_UNLESS($1 && $6);
+ add_join_natural($6,$1,NULL,Select);
+ LEX *lex= Lex;
+ if (!($$= lex->current_select->convert_right_join()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+inner_join: /* $$ set if using STRAIGHT_JOIN, false otherwise */
+ JOIN_SYM { $$ = 0; }
+ | INNER_SYM JOIN_SYM { $$ = 0; }
+ | STRAIGHT_JOIN { $$ = 1; }
+ ;
+
+normal_join:
+ inner_join { $$ = $1; }
+ | CROSS JOIN_SYM { $$ = 0; }
+ ;
+
+/*
+ table PARTITION (list of partitions), reusing using_list instead of creating
+ a new rule for partition_list.
+*/
+opt_use_partition:
+ /* empty */ { $$= 0;}
+ | use_partition
+ ;
+
+use_partition:
+ PARTITION_SYM '(' using_list ')' have_partitioning
+ {
+ $$= $3;
+ }
+ ;
+
+/*
+ This is a flattening of the rules <table factor> and <table primary>
+ in the SQL:2003 standard, since we don't have <sample clause>
+
+ I.e.
+ <table factor> ::= <table primary> [ <sample clause> ]
+*/
+/* Warning - may return NULL in case of incomplete SELECT */
+table_factor:
+ table_primary_ident
+ | table_primary_derived
+ ;
+
+table_primary_ident:
+ {
+ SELECT_LEX *sel= Select;
+ sel->table_join_options= 0;
+ }
+ table_ident opt_use_partition opt_table_alias opt_key_definition
+ {
+ if (!($$= Select->add_table_to_list(thd, $2, $4,
+ Select->get_table_join_options(),
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ Select->pop_index_hints(),
+ $3)))
+ MYSQL_YYABORT;
+ Select->add_joined_table($$);
+ }
+ ;
+
+
+
+/*
+ Represents a flattening of the following rules from the SQL:2003
+ standard. This sub-rule corresponds to the sub-rule
+ <table primary> ::= ... | <derived table> [ AS ] <correlation name>
+
+ <derived table> ::= <table subquery>
+ <table subquery> ::= <subquery>
+ <subquery> ::= <left paren> <query expression> <right paren>
+ <query expression> ::= [ <with clause> ] <query expression body>
+
+ For the time being we use the non-standard rule
+ select_derived_union which is a compromise between the standard
+ and our parser. Possibly this rule could be replaced by our
+ query_expression_body.
+*/
+
+table_primary_derived:
+ '(' get_select_lex select_derived_union ')' opt_table_alias
+ {
+ /* Use $2 instead of Lex->current_select as derived table will
+ alter value of Lex->current_select. */
+ if (!($3 || $5) && $2->embedding &&
+ !$2->embedding->nested_join->join_list.elements)
+ {
+ /* we have a derived table ($3 == NULL) but no alias,
+ Since we are nested in further parentheses so we
+ can pass NULL to the outer level parentheses
+ Permits parsing of "((((select ...))) as xyz)" */
+ $$= 0;
+ }
+ else if (!$3)
+ {
+ /* Handle case of derived table, alias may be NULL if there
+ are no outer parentheses, add_table_to_list() will throw
+ error in this case */
+ LEX *lex=Lex;
+ lex->check_automatic_up(UNSPECIFIED_TYPE);
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel->master_unit();
+ lex->current_select= sel= unit->outer_select();
+ Table_ident *ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ MYSQL_YYABORT;
+ if (!($$= sel->add_table_to_list(thd,
+ ti, $5, 0,
+ TL_READ, MDL_SHARED_READ)))
+
+ MYSQL_YYABORT;
+ sel->add_joined_table($$);
+ lex->pop_context();
+ lex->nest_level--;
+ }
+ else if ($5 != NULL)
+ {
+ /*
+ Tables with or without joins within parentheses cannot
+ have aliases, and we ruled out derived tables above.
+ */
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ else
+ {
+ /* nested join: FROM (t1 JOIN t2 ...),
+ nest_level is the same as in the outer query */
+ $$= $3;
+ }
+ /*
+ Fields in derived table can be used in upper select in
+ case of merge. We do not add HAVING fields because we do
+ not merge such derived. We do not add union because
+ also do not merge them
+ */
+ if ($$ && $$->derived &&
+ !$$->derived->first_select()->next_select())
+ $$->select_lex->add_where_field($$->derived->first_select());
+ }
+ /* Represents derived table with WITH clause */
+ | '(' get_select_lex subselect_start
+ with_clause query_expression_body
+ subselect_end ')' opt_table_alias
+ {
+ LEX *lex=Lex;
+ SELECT_LEX *sel= $2;
+ SELECT_LEX_UNIT *unit= $5->master_unit();
+ Table_ident *ti= new (thd->mem_root) Table_ident(unit);
+ if (ti == NULL)
+ MYSQL_YYABORT;
+ $5->set_with_clause($4);
+ lex->current_select= sel;
+ if (!($$= sel->add_table_to_list(lex->thd,
+ ti, $8, 0,
+ TL_READ, MDL_SHARED_READ)))
+ MYSQL_YYABORT;
+ sel->add_joined_table($$);
+ }
+ ;
+
+/*
+ This rule accepts just about anything. The reason is that we have
+ empty-producing rules in the beginning of rules, in this case
+ subselect_start. This forces bison to take a decision which rules to
+ reduce by long before it has seen any tokens. This approach ties us
+ to a very limited class of parseable languages, and unfortunately
+ SQL is not one of them. The chosen 'solution' was this rule, which
+ produces just about anything, even complete bogus statements, for
+ instance ( table UNION SELECT 1 ).
+ Fortunately, we know that the semantic value returned by
+ select_derived is NULL if it contained a derived table, and a pointer to
+ the base table's TABLE_LIST if it was a base table. So in the rule
+ regarding union's, we throw a parse error manually and pretend it
+ was bison that did it.
+
+ Also worth noting is that this rule concerns query expressions in
+ the from clause only. Top level select statements and other types of
+ subqueries have their own union rules.
+*/
+select_derived_union:
+ select_derived
+ | select_derived union_order_or_limit
+ {
+ if ($1)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ | select_derived union_head_non_top
+ {
+ if ($1)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ union_list_derived_part2
+ | derived_query_specification opt_select_lock_type
+ | derived_query_specification order_or_limit opt_select_lock_type
+ | derived_query_specification opt_select_lock_type union_list_derived
+ ;
+
+union_list_derived_part2:
+ query_term_union_not_ready { Lex->pop_context(); }
+ | query_term_union_ready { Lex->pop_context(); }
+ | query_term_union_ready { Lex->pop_context(); } union_list_derived
+ ;
+
+union_list_derived:
+ union_head_non_top union_list_derived_part2
+ ;
+
+
+/* The equivalent of select_init2 for nested queries. */
+select_init2_derived:
+ select_part2_derived
+ {
+ Select->set_braces(0);
+ }
+ ;
+
+/* The equivalent of select_part2 for nested queries. */
+select_part2_derived:
+ {
+ LEX *lex= Lex;
+ SELECT_LEX *sel= lex->current_select;
+ if (sel->linkage != UNION_TYPE)
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ }
+ opt_query_expression_options select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ ;
+
+/* handle contents of parentheses in join expression */
+select_derived:
+ get_select_lex_derived derived_table_list
+ {
+ LEX *lex= Lex;
+ /* for normal joins, $2 != NULL and end_nested_join() != NULL,
+ for derived tables, both must equal NULL */
+
+ if (!($$= $1->end_nested_join(lex->thd)) && $2)
+ MYSQL_YYABORT;
+ if (!$2 && $$)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+/*
+ Similar to query_specification, but for derived tables.
+ Example: the inner parenthesized SELECT in this query:
+ SELECT * FROM (SELECT * FROM t1);
+*/
+derived_query_specification:
+ SELECT_SYM select_derived_init select_derived2
+ {
+ if ($2)
+ Select->set_braces(1);
+ $$= NULL;
+ }
+ ;
+
+select_derived2:
+ {
+ LEX *lex= Lex;
+ lex->derived_tables|= DERIVED_SUBQUERY;
+ if (!lex->expr_allows_subselect ||
+ lex->sql_command == (int)SQLCOM_PURGE)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
+ mysql_new_select(lex, 1, NULL))
+ MYSQL_YYABORT;
+ mysql_init_select(lex);
+ lex->current_select->linkage= DERIVED_TABLE_TYPE;
+ lex->current_select->parsing_place= SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ opt_table_expression
+ ;
+
+get_select_lex:
+ /* Empty */ { $$= Select; }
+ ;
+
+get_select_lex_derived:
+ get_select_lex
+ {
+ LEX *lex= Lex;
+ if ($1->init_nested_join(lex->thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+select_derived_init:
+ {
+ LEX *lex= Lex;
+
+ TABLE_LIST *embedding= lex->current_select->embedding;
+ $$= embedding &&
+ !embedding->nested_join->join_list.elements;
+ /* return true if we are deeply nested */
+ }
+ ;
+
+opt_outer:
+ /* empty */ {}
+ | OUTER {}
+ ;
+
+index_hint_clause:
+ /* empty */
+ {
+ $$= thd->variables.old_mode ? INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL;
+ }
+ | FOR_SYM JOIN_SYM { $$= INDEX_HINT_MASK_JOIN; }
+ | FOR_SYM ORDER_SYM BY { $$= INDEX_HINT_MASK_ORDER; }
+ | FOR_SYM GROUP_SYM BY { $$= INDEX_HINT_MASK_GROUP; }
+ ;
+
+index_hint_type:
+ FORCE_SYM { $$= INDEX_HINT_FORCE; }
+ | IGNORE_SYM { $$= INDEX_HINT_IGNORE; }
+ ;
+
+index_hint_definition:
+ index_hint_type key_or_index index_hint_clause
+ {
+ Select->set_index_hint_type($1, $3);
+ }
+ '(' key_usage_list ')'
+ | USE_SYM key_or_index index_hint_clause
+ {
+ Select->set_index_hint_type(INDEX_HINT_USE, $3);
+ }
+ '(' opt_key_usage_list ')'
+ ;
+
+index_hints_list:
+ index_hint_definition
+ | index_hints_list index_hint_definition
+ ;
+
+opt_index_hints_list:
+ /* empty */
+ | { Select->alloc_index_hints(thd); } index_hints_list
+ ;
+
+opt_key_definition:
+ { Select->clear_index_hints(); }
+ opt_index_hints_list
+ ;
+
+opt_key_usage_list:
+ /* empty */ { Select->add_index_hint(thd, NULL, 0); }
+ | key_usage_list {}
+ ;
+
+key_usage_element:
+ ident
+ { Select->add_index_hint(thd, $1.str, $1.length); }
+ | PRIMARY_SYM
+ { Select->add_index_hint(thd, "PRIMARY", 7); }
+ ;
+
+key_usage_list:
+ key_usage_element
+ | key_usage_list ',' key_usage_element
+ ;
+
+using_list:
+ ident
+ {
+ if (!($$= new (thd->mem_root) List<String>))
+ MYSQL_YYABORT;
+ String *s= new (thd->mem_root) String((const char *) $1.str,
+ $1.length,
+ system_charset_info);
+ if (s == NULL)
+ MYSQL_YYABORT;
+ $$->push_back(s, thd->mem_root);
+ }
+ | using_list ',' ident
+ {
+ String *s= new (thd->mem_root) String((const char *) $3.str,
+ $3.length,
+ system_charset_info);
+ if (s == NULL)
+ MYSQL_YYABORT;
+ $1->push_back(s, thd->mem_root);
+ $$= $1;
+ }
+ ;
+
+interval:
+ interval_time_stamp {}
+ | DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
+ | DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; }
+ | DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; }
+ | DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; }
+ | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
+ | HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
+ | HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
+ | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
+ | MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
+ | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
+ | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
+ ;
+
+interval_time_stamp:
+ DAY_SYM { $$=INTERVAL_DAY; }
+ | WEEK_SYM { $$=INTERVAL_WEEK; }
+ | HOUR_SYM { $$=INTERVAL_HOUR; }
+ | MINUTE_SYM { $$=INTERVAL_MINUTE; }
+ | MONTH_SYM { $$=INTERVAL_MONTH; }
+ | QUARTER_SYM { $$=INTERVAL_QUARTER; }
+ | SECOND_SYM { $$=INTERVAL_SECOND; }
+ | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
+ | YEAR_SYM { $$=INTERVAL_YEAR; }
+ ;
+
+date_time_type:
+ DATE_SYM {$$=MYSQL_TIMESTAMP_DATE;}
+ | TIME_SYM {$$=MYSQL_TIMESTAMP_TIME;}
+ | DATETIME {$$=MYSQL_TIMESTAMP_DATETIME;}
+ | TIMESTAMP {$$=MYSQL_TIMESTAMP_DATETIME;}
+ ;
+
+table_alias:
+ /* empty */
+ | AS
+ | '='
+ ;
+
+opt_table_alias:
+ /* empty */ { $$=0; }
+ | table_alias ident
+ {
+ $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_all:
+ /* empty */
+ | ALL
+ ;
+
+opt_where_clause:
+ /* empty */ { Select->where= 0; }
+ | WHERE
+ {
+ Select->parsing_place= IN_WHERE;
+ }
+ expr
+ {
+ SELECT_LEX *select= Select;
+ select->where= normalize_cond(thd, $3);
+ select->parsing_place= NO_MATTER;
+ if ($3)
+ $3->top_level_item();
+ }
+ ;
+
+opt_having_clause:
+ /* empty */
+ | HAVING
+ {
+ Select->parsing_place= IN_HAVING;
+ }
+ expr
+ {
+ SELECT_LEX *sel= Select;
+ sel->having= normalize_cond(thd, $3);
+ sel->parsing_place= NO_MATTER;
+ if ($3)
+ $3->top_level_item();
+ }
+ ;
+
+opt_escape:
+ ESCAPE_SYM simple_expr
+ {
+ Lex->escape_used= TRUE;
+ $$= $2;
+ }
+ | /* empty */
+ {
+ Lex->escape_used= FALSE;
+ $$= ((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
+ new (thd->mem_root) Item_string_ascii(thd, "", 0) :
+ new (thd->mem_root) Item_string_ascii(thd, "\\", 1));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+/*
+ group by statement in select
+*/
+
+opt_group_clause:
+ /* empty */
+ | GROUP_SYM BY group_list olap_opt
+ ;
+
+group_list:
+ group_list ',' order_ident order_dir
+ { if (add_group_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
+ | order_ident order_dir
+ { if (add_group_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
+ ;
+
+olap_opt:
+ /* empty */ {}
+ | WITH_CUBE_SYM
+ {
+ /*
+ 'WITH CUBE' is reserved in the MySQL syntax, but not implemented,
+ and cause LALR(2) conflicts.
+ This syntax is not standard.
+ MySQL syntax: GROUP BY col1, col2, col3 WITH CUBE
+ SQL-2003: GROUP BY ... CUBE(col1, col2, col3)
+ */
+ LEX *lex=Lex;
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
+ "global union parameters"));
+ lex->current_select->olap= CUBE_TYPE;
+
+ my_yyabort_error((ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"));
+ }
+ | WITH_ROLLUP_SYM
+ {
+ /*
+ 'WITH ROLLUP' is needed for backward compatibility,
+ and cause LALR(2) conflicts.
+ This syntax is not standard.
+ MySQL syntax: GROUP BY col1, col2, col3 WITH ROLLUP
+ SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3)
+ */
+ LEX *lex= Lex;
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
+ "global union parameters"));
+ lex->current_select->olap= ROLLUP_TYPE;
+ }
+ ;
+
+/*
+ optional window clause in select
+*/
+
+opt_window_clause:
+ /* empty */
+ {}
+ | WINDOW_SYM
+ window_def_list
+ {}
+ ;
+
+window_def_list:
+ window_def_list ',' window_def
+ | window_def
+ ;
+
+window_def:
+ window_name AS window_spec
+ {
+ LEX *lex= Lex;
+ if (Select->add_window_def(thd, $1, lex->win_ref,
+ Select->group_list,
+ Select->order_list,
+ lex->win_frame))
+ MYSQL_YYABORT;
+ }
+ ;
+
+window_spec:
+ '('
+ { Select->prepare_add_window_spec(thd); }
+ opt_window_ref opt_window_partition_clause
+ opt_window_order_clause opt_window_frame_clause
+ ')'
+ ;
+
+opt_window_ref:
+ /* empty */ {}
+ | ident
+ {
+ thd->lex->win_ref= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
+ if (thd->lex->win_ref == NULL)
+ MYSQL_YYABORT;
+ }
+
+opt_window_partition_clause:
+ /* empty */ { }
+ | PARTITION_SYM BY group_list
+ ;
+
+opt_window_order_clause:
+ /* empty */ { }
+ | ORDER_SYM BY order_list
+ ;
+
+opt_window_frame_clause:
+ /* empty */ {}
+ | window_frame_units window_frame_extent opt_window_frame_exclusion
+ {
+ LEX *lex= Lex;
+ lex->win_frame=
+ new (thd->mem_root) Window_frame($1,
+ lex->frame_top_bound,
+ lex->frame_bottom_bound,
+ $3);
+ if (lex->win_frame == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+window_frame_units:
+ ROWS_SYM { $$= Window_frame::UNITS_ROWS; }
+ | RANGE_SYM { $$= Window_frame::UNITS_RANGE; }
+ ;
+
+window_frame_extent:
+ window_frame_start
+ {
+ LEX *lex= Lex;
+ lex->frame_top_bound= $1;
+ lex->frame_bottom_bound=
+ new (thd->mem_root)
+ Window_frame_bound(Window_frame_bound::CURRENT, NULL);
+ if (lex->frame_bottom_bound == NULL)
+ MYSQL_YYABORT;
+ }
+ | BETWEEN_SYM window_frame_bound AND_SYM window_frame_bound
+ {
+ LEX *lex= Lex;
+ lex->frame_top_bound= $2;
+ lex->frame_bottom_bound= $4;
+ }
+ ;
+
+window_frame_start:
+ UNBOUNDED_SYM PRECEDING_SYM
+ {
+ $$= new (thd->mem_root)
+ Window_frame_bound(Window_frame_bound::PRECEDING, NULL);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | CURRENT_SYM ROW_SYM
+ {
+ $$= new (thd->mem_root)
+ Window_frame_bound(Window_frame_bound::CURRENT, NULL);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | literal PRECEDING_SYM
+ {
+ $$= new (thd->mem_root)
+ Window_frame_bound(Window_frame_bound::PRECEDING, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+window_frame_bound:
+ window_frame_start { $$= $1; }
+ | UNBOUNDED_SYM FOLLOWING_SYM
+ {
+ $$= new (thd->mem_root)
+ Window_frame_bound(Window_frame_bound::FOLLOWING, NULL);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | literal FOLLOWING_SYM
+ {
+ $$= new (thd->mem_root)
+ Window_frame_bound(Window_frame_bound::FOLLOWING, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_window_frame_exclusion:
+ /* empty */ { $$= Window_frame::EXCL_NONE; }
+ | EXCLUDE_SYM CURRENT_SYM ROW_SYM
+ { $$= Window_frame::EXCL_CURRENT_ROW; }
+ | EXCLUDE_SYM GROUP_SYM
+ { $$= Window_frame::EXCL_GROUP; }
+ | EXCLUDE_SYM TIES_SYM
+ { $$= Window_frame::EXCL_TIES; }
+ | EXCLUDE_SYM NO_SYM OTHERS_SYM
+ { $$= Window_frame::EXCL_NONE; }
+ ;
+
+/*
+ Order by statement in ALTER TABLE
+*/
+
+alter_order_clause:
+ ORDER_SYM BY alter_order_list
+ ;
+
+alter_order_list:
+ alter_order_list ',' alter_order_item
+ | alter_order_item
+ ;
+
+alter_order_item:
+ simple_ident_nospvar order_dir
+ {
+ bool ascending= ($2 == 1) ? true : false;
+ if (add_order_to_list(thd, $1, ascending))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/*
+ Order by statement in select
+*/
+
+opt_order_clause:
+ /* empty */
+ | order_clause
+ ;
+
+order_clause:
+ ORDER_SYM BY
+ {
+ LEX *lex=Lex;
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel-> master_unit();
+ if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
+ sel->olap != UNSPECIFIED_OLAP_TYPE &&
+ (sel->linkage != UNION_TYPE || sel->braces))
+ {
+ my_error(ER_WRONG_USAGE, MYF(0),
+ "CUBE/ROLLUP", "ORDER BY");
+ MYSQL_YYABORT;
+ }
+ if (lex->sql_command != SQLCOM_ALTER_TABLE &&
+ !unit->fake_select_lex)
+ {
+ /*
+ A query of the of the form (SELECT ...) ORDER BY order_list is
+ executed in the same way as the query
+ SELECT ... ORDER BY order_list
+ unless the SELECT construct contains ORDER BY or LIMIT clauses.
+ Otherwise we create a fake SELECT_LEX if it has not been created
+ yet.
+ */
+ SELECT_LEX *first_sl= unit->first_select();
+ if (!unit->is_unit_op() &&
+ (first_sl->order_list.elements ||
+ first_sl->select_limit) &&
+ unit->add_fake_select_lex(thd))
+ MYSQL_YYABORT;
+ }
+ if (sel->master_unit()->is_unit_op() && !sel->braces)
+ {
+ /*
+ At this point we don't know yet whether this is the last
+ select in union or not, but we move ORDER BY to
+ fake_select_lex anyway. If there would be one more select
+ in union mysql_new_select will correctly throw error.
+ */
+ DBUG_ASSERT(sel->master_unit()->fake_select_lex);
+ lex->current_select= sel->master_unit()->fake_select_lex;
+ }
+ }
+ order_list
+ {
+
+ }
+ ;
+
+order_list:
+ order_list ',' order_ident order_dir
+ { if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
+ | order_ident order_dir
+ { if (add_order_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
+ ;
+
+order_dir:
+ /* empty */ { $$ = 1; }
+ | ASC { $$ =1; }
+ | DESC { $$ =0; }
+ ;
+
+opt_limit_clause:
+ /* empty */ {}
+ | limit_clause {}
+ ;
+
+limit_clause_init:
+ LIMIT
+ {
+ SELECT_LEX *sel= Select;
+ if (sel->master_unit()->is_unit_op() && !sel->braces)
+ {
+ /* Move LIMIT that belongs to UNION to fake_select_lex */
+ Lex->current_select= sel->master_unit()->fake_select_lex;
+ DBUG_ASSERT(Select);
+ }
+ }
+ ;
+
+limit_clause:
+ limit_clause_init limit_options
+ {
+ SELECT_LEX *sel= Select;
+ if (!sel->select_limit->basic_const_item() ||
+ sel->select_limit->val_int() > 0)
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
+ }
+ | limit_clause_init limit_options
+ ROWS_SYM EXAMINED_SYM limit_rows_option
+ {
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
+ }
+ | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option
+ {
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
+ }
+ ;
+
+limit_options:
+ limit_option
+ {
+ SELECT_LEX *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= 0;
+ sel->explicit_limit= 1;
+ }
+ | limit_option ',' limit_option
+ {
+ SELECT_LEX *sel= Select;
+ sel->select_limit= $3;
+ sel->offset_limit= $1;
+ sel->explicit_limit= 1;
+ }
+ | limit_option OFFSET_SYM limit_option
+ {
+ SELECT_LEX *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= $3;
+ sel->explicit_limit= 1;
+ }
+ ;
+
+limit_option:
+ ident_with_tok_start
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= & thd->m_parser_state->m_lip;
+ if (!($$= lex->create_item_limit(thd, &$1,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
+ | ident_with_tok_start '.' ident
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= & thd->m_parser_state->m_lip;
+ if (!($$= lex->create_item_limit(thd, &$1, &$3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_ptr() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
+ | param_marker
+ {
+ $1->limit_clause_param= TRUE;
+ }
+ | ULONGLONG_NUM
+ {
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | LONG_NUM
+ {
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | NUM
+ {
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+limit_rows_option:
+ limit_option
+ {
+ LEX *lex=Lex;
+ lex->limit_rows_examined= $1;
+ }
+
+delete_limit_clause:
+ /* empty */
+ {
+ LEX *lex=Lex;
+ lex->current_select->select_limit= 0;
+ }
+ | LIMIT limit_option
+ {
+ SELECT_LEX *sel= Select;
+ sel->select_limit= $2;
+ Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
+ sel->explicit_limit= 1;
+ }
+ | LIMIT ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
+ | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
+ ;
+
+opt_plus:
+ /* empty */
+ | '+'
+ ;
+
+int_num:
+ opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); }
+ | '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
+
+ulong_num:
+ opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
+ | opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ ;
+
+real_ulong_num:
+ NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
+ | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | dec_num_error { MYSQL_YYABORT; }
+ ;
+
+longlong_num:
+ opt_plus NUM { int error; $$= (longlong) my_strtoll10($2.str, (char**) 0, &error); }
+ | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
+ | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
+ | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
+
+
+ulonglong_num:
+ opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ ;
+
+real_ulonglong_num:
+ NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ | HEX_NUM { $$= strtoull($1.str, (char**) 0, 16); }
+ | LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ | dec_num_error { MYSQL_YYABORT; }
+ ;
+
+dec_num_error:
+ dec_num
+ { thd->parse_error(ER_ONLY_INTEGERS_ALLOWED); }
+ ;
+
+dec_num:
+ DECIMAL_NUM
+ | FLOAT_NUM
+ ;
+
+choice:
+ ulong_num { $$= $1 != 0 ? HA_CHOICE_YES : HA_CHOICE_NO; }
+ | DEFAULT { $$= HA_CHOICE_UNDEF; }
+ ;
+
+bool:
+ ulong_num { $$= $1 != 0; }
+ | TRUE_SYM { $$= 1; }
+ | FALSE_SYM { $$= 0; }
+
+
+procedure_clause:
+ PROCEDURE_SYM ident /* Procedure name */
+ {
+ LEX *lex=Lex;
+
+ DBUG_ASSERT(&lex->select_lex == lex->current_select);
+
+ lex->proc_list.elements=0;
+ lex->proc_list.first=0;
+ lex->proc_list.next= &lex->proc_list.first;
+ Item_field *item= new (thd->mem_root)
+ Item_field(thd, &lex->current_select->context,
+ NULL, NULL, &$2);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ if (add_proc_to_list(thd, item))
+ MYSQL_YYABORT;
+ Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+
+ /*
+ PROCEDURE CLAUSE cannot handle subquery as one of its parameter,
+ so set expr_allows_subselect as false to disallow any subqueries
+ further. Reset expr_allows_subselect back to true once the
+ parameters are reduced.
+ */
+ Lex->expr_allows_subselect= false;
+ }
+ '(' procedure_list ')'
+ {
+ /* Subqueries are allowed from now.*/
+ Lex->expr_allows_subselect= true;
+ }
+ ;
+
+procedure_list:
+ /* empty */ {}
+ | procedure_list2 {}
+ ;
+
+procedure_list2:
+ procedure_list2 ',' procedure_item
+ | procedure_item
+ ;
+
+procedure_item:
+ remember_name expr remember_end
+ {
+ if (add_proc_to_list(thd, $2))
+ MYSQL_YYABORT;
+ if (!$2->name.str || $2->name.str == item_empty_name)
+ $2->set_name(thd, $1, (uint) ($3 - $1), thd->charset());
+ }
+ ;
+
+select_var_list_init:
+ {
+ LEX *lex=Lex;
+ if (!lex->describe &&
+ (!(lex->result= new (thd->mem_root) select_dumpvar(thd))))
+ MYSQL_YYABORT;
+ }
+ select_var_list
+ {}
+ ;
+
+select_var_list:
+ select_var_list ',' select_var_ident
+ | select_var_ident {}
+ ;
+
+select_var_ident: select_outvar
+ {
+ if (Lex->result)
+ {
+ if ($1 == NULL)
+ MYSQL_YYABORT;
+ ((select_dumpvar *)Lex->result)->var_list.push_back($1, thd->mem_root);
+ }
+ else
+ {
+ /*
+ The parser won't create select_result instance only
+ if it's an EXPLAIN.
+ */
+ DBUG_ASSERT(Lex->describe);
+ }
+ }
+ ;
+
+select_outvar:
+ '@' ident_or_text
+ {
+ $$ = Lex->result ? new (thd->mem_root) my_var_user(&$2) : NULL;
+ }
+ | ident_or_text
+ {
+ sp_variable *t;
+
+ if (!Lex->spcont || !(t= Lex->spcont->find_variable(&$1, false)))
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
+ $$ = Lex->result ? (new (thd->mem_root)
+ my_var_sp(&$1, t->offset, t->type_handler(),
+ Lex->sphead)) :
+ NULL;
+ }
+ | ident '.' ident
+ {
+ if (!($$= Lex->create_outvar(thd, &$1, &$3)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+into:
+ INTO into_destination
+ ;
+
+into_destination:
+ OUTFILE TEXT_STRING_filesystem
+ {
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ if (!(lex->exchange=
+ new (thd->mem_root) sql_exchange($2.str, 0)) ||
+ !(lex->result=
+ new (thd->mem_root) select_export(thd, lex->exchange)))
+ MYSQL_YYABORT;
+ }
+ opt_load_data_charset
+ { Lex->exchange->cs= $4; }
+ opt_field_term opt_line_term
+ | DUMPFILE TEXT_STRING_filesystem
+ {
+ LEX *lex=Lex;
+ if (!lex->describe)
+ {
+ lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ if (!(lex->exchange= new (thd->mem_root) sql_exchange($2.str,1)))
+ MYSQL_YYABORT;
+ if (!(lex->result=
+ new (thd->mem_root) select_dump(thd, lex->exchange)))
+ MYSQL_YYABORT;
+ }
+ }
+ | select_var_list_init
+ {
+ Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ }
+ ;
+
+/*
+ DO statement
+*/
+
+do:
+ DO_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_DO;
+ mysql_init_select(lex);
+ }
+ expr_list
+ {
+ Lex->insert_list= $3;
+ }
+ ;
+
+/*
+ Drop : delete tables or index or user
+*/
+
+drop:
+ DROP opt_temporary table_or_tables opt_if_exists
+ {
+ LEX *lex=Lex;
+ lex->set_command(SQLCOM_DROP_TABLE, $2, $4);
+ YYPS->m_lock_type= TL_UNLOCK;
+ YYPS->m_mdl_type= MDL_EXCLUSIVE;
+ }
+ table_list opt_restrict
+ {}
+ | DROP INDEX_SYM opt_if_exists_table_element ident ON table_ident {}
+ {
+ LEX *lex=Lex;
+ Alter_drop *ad= (new (thd->mem_root)
+ Alter_drop(Alter_drop::KEY, $4.str, $3));
+ if (ad == NULL)
+ MYSQL_YYABORT;
+ lex->sql_command= SQLCOM_DROP_INDEX;
+ lex->alter_info.reset();
+ lex->alter_info.flags= Alter_info::ALTER_DROP_INDEX;
+ lex->alter_info.drop_list.push_back(ad, thd->mem_root);
+ if (!lex->current_select->add_table_to_list(thd, $6, NULL,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_UPGRADABLE))
+ MYSQL_YYABORT;
+ }
+ | DROP DATABASE opt_if_exists ident
+ {
+ LEX *lex=Lex;
+ lex->set_command(SQLCOM_DROP_DB, $3);
+ lex->name= $4;
+ }
+ | DROP FUNCTION_SYM opt_if_exists ident '.' ident
+ {
+ LEX *lex= thd->lex;
+ sp_name *spname;
+ if ($4.str && check_db_name((LEX_STRING*) &$4))
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $4.str));
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+ lex->set_command(SQLCOM_DROP_FUNCTION, $3);
+ spname= new (thd->mem_root) sp_name(&$4, &$6, true);
+ if (spname == NULL)
+ MYSQL_YYABORT;
+ lex->spname= spname;
+ }
+ | DROP FUNCTION_SYM opt_if_exists ident
+ {
+ LEX *lex= thd->lex;
+ LEX_CSTRING db= {0, 0};
+ sp_name *spname;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
+ if (thd->db && lex->copy_db_to(&db.str, &db.length))
+ MYSQL_YYABORT;
+ lex->set_command(SQLCOM_DROP_FUNCTION, $3);
+ spname= new (thd->mem_root) sp_name(&db, &$4, false);
+ if (spname == NULL)
+ MYSQL_YYABORT;
+ lex->spname= spname;
+ }
+ | DROP PROCEDURE_SYM opt_if_exists sp_name
+ {
+ LEX *lex=Lex;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
+ lex->set_command(SQLCOM_DROP_PROCEDURE, $3);
+ lex->spname= $4;
+ }
+ | DROP USER_SYM opt_if_exists clear_privileges user_list
+ {
+ Lex->set_command(SQLCOM_DROP_USER, $3);
+ }
+ | DROP ROLE_SYM opt_if_exists clear_privileges role_list
+ {
+ Lex->set_command(SQLCOM_DROP_ROLE, $3);
+ }
+ | DROP VIEW_SYM opt_if_exists
+ {
+ LEX *lex= Lex;
+ lex->set_command(SQLCOM_DROP_VIEW, $3);
+ YYPS->m_lock_type= TL_UNLOCK;
+ YYPS->m_mdl_type= MDL_EXCLUSIVE;
+ }
+ table_list opt_restrict
+ {}
+ | DROP EVENT_SYM opt_if_exists sp_name
+ {
+ Lex->spname= $4;
+ Lex->set_command(SQLCOM_DROP_EVENT, $3);
+ }
+ | DROP TRIGGER_SYM opt_if_exists sp_name
+ {
+ LEX *lex= Lex;
+ lex->set_command(SQLCOM_DROP_TRIGGER, $3);
+ lex->spname= $4;
+ }
+ | DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_cmd_type= DROP_TABLESPACE;
+ }
+ | DROP LOGFILE_SYM GROUP_SYM logfile_group_name opt_ts_engine opt_ts_wait
+ {
+ LEX *lex= Lex;
+ lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP;
+ }
+ | DROP SERVER_SYM opt_if_exists ident_or_text
+ {
+ Lex->set_command(SQLCOM_DROP_SERVER, $3);
+ Lex->server_options.reset($4);
+ }
+ | DROP opt_temporary SEQUENCE_SYM opt_if_exists
+
+ {
+ LEX *lex= Lex;
+ lex->set_command(SQLCOM_DROP_SEQUENCE, $2, $4);
+ lex->table_type= TABLE_TYPE_SEQUENCE;
+ YYPS->m_lock_type= TL_UNLOCK;
+ YYPS->m_mdl_type= MDL_EXCLUSIVE;
+ }
+ table_list
+ {}
+ ;
+
+table_list:
+ table_name
+ | table_list ',' table_name
+ ;
+
+table_name:
+ table_ident
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL,
+ TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type))
+ MYSQL_YYABORT;
+ }
+ ;
+
+table_name_with_opt_use_partition:
+ table_ident opt_use_partition
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL,
+ TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
+ $2))
+ MYSQL_YYABORT;
+ }
+ ;
+
+table_alias_ref_list:
+ table_alias_ref
+ | table_alias_ref_list ',' table_alias_ref
+ ;
+
+table_alias_ref:
+ table_ident_opt_wild
+ {
+ if (!Select->add_table_to_list(thd, $1, NULL,
+ TL_OPTION_UPDATING | TL_OPTION_ALIAS,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_if_exists_table_element:
+ /* empty */
+ {
+ Lex->check_exists= FALSE;
+ $$= 0;
+ }
+ | IF_SYM EXISTS
+ {
+ Lex->check_exists= TRUE;
+ $$= 1;
+ }
+ ;
+
+opt_if_exists:
+ /* empty */
+ {
+ $$.set(DDL_options_st::OPT_NONE);
+ }
+ | IF_SYM EXISTS
+ {
+ $$.set(DDL_options_st::OPT_IF_EXISTS);
+ }
+ ;
+
+opt_temporary:
+ /* empty */ { $$= 0; }
+ | TEMPORARY { $$= HA_LEX_CREATE_TMP_TABLE; }
+ ;
+/*
+** Insert : add new data to table
+*/
+
+insert:
+ INSERT
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_INSERT;
+ lex->duplicates= DUP_ERROR;
+ mysql_init_select(lex);
+ }
+ insert_lock_option
+ opt_ignore insert2
+ {
+ Select->set_lock_for_tables($3);
+ Lex->current_select= &Lex->select_lex;
+ }
+ insert_field_spec opt_insert_update
+ {}
+ ;
+
+replace:
+ REPLACE
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_REPLACE;
+ lex->duplicates= DUP_REPLACE;
+ mysql_init_select(lex);
+ }
+ replace_lock_option insert2
+ {
+ Select->set_lock_for_tables($3);
+ Lex->current_select= &Lex->select_lex;
+ }
+ insert_field_spec
+ {}
+ ;
+
+insert_lock_option:
+ /* empty */
+ {
+ /*
+ If it is SP we do not allow insert optimisation when result of
+ insert visible only after the table unlocking but everyone can
+ read table.
+ */
+ $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
+ }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
+ | DELAYED_SYM
+ {
+ Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
+ thd->query());
+ Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
+ YYLIP->yyLength() + 1;
+ $$= TL_WRITE_DELAYED;
+ }
+ | HIGH_PRIORITY { $$= TL_WRITE; }
+ ;
+
+replace_lock_option:
+ opt_low_priority { $$= $1; }
+ | DELAYED_SYM
+ {
+ Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
+ thd->query());
+ Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
+ YYLIP->yyLength() + 1;
+ $$= TL_WRITE_DELAYED;
+ }
+ ;
+
+insert2:
+ INTO insert_table {}
+ | insert_table {}
+ ;
+
+insert_table:
+ table_name_with_opt_use_partition
+ {
+ LEX *lex=Lex;
+ lex->field_list.empty();
+ lex->many_values.empty();
+ lex->insert_list=0;
+ };
+
+insert_field_spec:
+ insert_values {}
+ | '(' ')' insert_values {}
+ | '(' fields ')' insert_values {}
+ | SET
+ {
+ LEX *lex=Lex;
+ if (!(lex->insert_list= new (thd->mem_root) List_item) ||
+ lex->many_values.push_back(lex->insert_list, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ident_eq_list
+ ;
+
+fields:
+ fields ',' insert_ident
+ { Lex->field_list.push_back($3, thd->mem_root); }
+ | insert_ident { Lex->field_list.push_back($1, thd->mem_root); }
+ ;
+
+insert_values:
+ VALUES values_list {}
+ | VALUE_SYM values_list {}
+ | create_select_query_expression {}
+ ;
+
+values_list:
+ values_list ',' no_braces
+ | no_braces
+ ;
+
+ident_eq_list:
+ ident_eq_list ',' ident_eq_value
+ | ident_eq_value
+ ;
+
+ident_eq_value:
+ simple_ident_nospvar equal expr_or_default
+ {
+ LEX *lex=Lex;
+ if (lex->field_list.push_back($1, thd->mem_root) ||
+ lex->insert_list->push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+equal:
+ '=' {}
+ | SET_VAR {}
+ ;
+
+opt_equal:
+ /* empty */ {}
+ | equal {}
+ ;
+
+opt_with:
+ opt_equal {}
+ | WITH {}
+ ;
+
+opt_by:
+ opt_equal {}
+ | BY {}
+ ;
+
+no_braces:
+ '('
+ {
+ if (!(Lex->insert_list= new (thd->mem_root) List_item))
+ MYSQL_YYABORT;
+ }
+ opt_values ')'
+ {
+ LEX *lex=Lex;
+ if (lex->many_values.push_back(lex->insert_list, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_values:
+ /* empty */ {}
+ | values
+ ;
+
+values:
+ values ',' expr_or_default
+ {
+ if (Lex->insert_list->push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | expr_or_default
+ {
+ if (Lex->insert_list->push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+expr_or_default:
+ expr { $$= $1;}
+ | DEFAULT
+ {
+ $$= new (thd->mem_root) Item_default_value(thd, Lex->current_context());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | IGNORE_SYM
+ {
+ $$= new (thd->mem_root) Item_ignore_value(thd, Lex->current_context());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_insert_update:
+ /* empty */
+ | ON DUPLICATE_SYM { Lex->duplicates= DUP_UPDATE; }
+ KEY_SYM UPDATE_SYM insert_update_list
+ ;
+
+/* Update rows in a table */
+
+update:
+ UPDATE_SYM
+ {
+ LEX *lex= Lex;
+ mysql_init_select(lex);
+ lex->sql_command= SQLCOM_UPDATE;
+ lex->duplicates= DUP_ERROR;
+ }
+ opt_low_priority opt_ignore join_table_list
+ SET update_list
+ {
+ LEX *lex= Lex;
+ if (lex->select_lex.table_list.elements > 1)
+ lex->sql_command= SQLCOM_UPDATE_MULTI;
+ else if (lex->select_lex.get_table_list()->derived)
+ {
+ /* it is single table update and it is update of derived table */
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ lex->select_lex.get_table_list()->alias, "UPDATE");
+ MYSQL_YYABORT;
+ }
+ /*
+ In case of multi-update setting write lock for all tables may
+ be too pessimistic. We will decrease lock level if possible in
+ mysql_multi_update().
+ */
+ Select->set_lock_for_tables($3);
+ }
+ opt_where_clause opt_order_clause delete_limit_clause {}
+ ;
+
+update_list:
+ update_list ',' update_elem
+ | update_elem
+ ;
+
+update_elem:
+ simple_ident_nospvar equal expr_or_default
+ {
+ if (add_item_to_list(thd, $1) || add_value_to_list(thd, $3))
+ MYSQL_YYABORT;
+ }
+ ;
+
+insert_update_list:
+ insert_update_list ',' insert_update_elem
+ | insert_update_elem
+ ;
+
+insert_update_elem:
+ simple_ident_nospvar equal expr_or_default
+ {
+ LEX *lex= Lex;
+ if (lex->update_list.push_back($1, thd->mem_root) ||
+ lex->value_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_low_priority:
+ /* empty */ { $$= TL_WRITE_DEFAULT; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
+ ;
+
+/* Delete rows from a table */
+
+delete:
+ DELETE_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_DELETE;
+ mysql_init_select(lex);
+ YYPS->m_lock_type= TL_WRITE_DEFAULT;
+ YYPS->m_mdl_type= MDL_SHARED_WRITE;
+
+ lex->ignore= 0;
+ lex->select_lex.init_order();
+ }
+ opt_delete_options single_multi
+ ;
+
+single_multi:
+ FROM table_ident opt_use_partition
+ {
+ if (!Select->add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type,
+ NULL,
+ $3))
+ MYSQL_YYABORT;
+ YYPS->m_lock_type= TL_READ_DEFAULT;
+ YYPS->m_mdl_type= MDL_SHARED_READ;
+ }
+ opt_where_clause opt_order_clause
+ delete_limit_clause {}
+ opt_select_expressions {}
+ | table_wild_list
+ {
+ mysql_init_multi_delete(Lex);
+ YYPS->m_lock_type= TL_READ_DEFAULT;
+ YYPS->m_mdl_type= MDL_SHARED_READ;
+ }
+ FROM join_table_list opt_where_clause
+ {
+ if (multi_delete_set_locks_and_link_aux_tables(Lex))
+ MYSQL_YYABORT;
+ }
+ | FROM table_alias_ref_list
+ {
+ mysql_init_multi_delete(Lex);
+ YYPS->m_lock_type= TL_READ_DEFAULT;
+ YYPS->m_mdl_type= MDL_SHARED_READ;
+ }
+ USING join_table_list opt_where_clause
+ {
+ if (multi_delete_set_locks_and_link_aux_tables(Lex))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_select_expressions:
+ /* empty */
+ | RETURNING_SYM select_item_list
+ ;
+
+table_wild_list:
+ table_wild_one
+ | table_wild_list ',' table_wild_one
+ ;
+
+table_wild_one:
+ ident opt_wild
+ {
+ Table_ident *ti= new (thd->mem_root) Table_ident(&$1);
+ if (ti == NULL)
+ MYSQL_YYABORT;
+ if (!Select->add_table_to_list(thd,
+ ti,
+ NULL,
+ TL_OPTION_UPDATING | TL_OPTION_ALIAS,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident opt_wild
+ {
+ Table_ident *ti= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
+ if (ti == NULL)
+ MYSQL_YYABORT;
+ if (!Select->add_table_to_list(thd,
+ ti,
+ NULL,
+ TL_OPTION_UPDATING | TL_OPTION_ALIAS,
+ YYPS->m_lock_type,
+ YYPS->m_mdl_type))
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_wild:
+ /* empty */ {}
+ | '.' '*' {}
+ ;
+
+opt_delete_options:
+ /* empty */ {}
+ | opt_delete_option opt_delete_options {}
+ ;
+
+opt_delete_option:
+ QUICK { Select->options|= OPTION_QUICK; }
+ | LOW_PRIORITY { YYPS->m_lock_type= TL_WRITE_LOW_PRIORITY; }
+ | IGNORE_SYM { Lex->ignore= 1; }
+ ;
+
+truncate:
+ TRUNCATE_SYM opt_table_sym
+ {
+ LEX* lex= Lex;
+ lex->sql_command= SQLCOM_TRUNCATE;
+ lex->alter_info.reset();
+ lex->select_lex.options= 0;
+ lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
+ lex->select_lex.init_order();
+ YYPS->m_lock_type= TL_WRITE;
+ YYPS->m_mdl_type= MDL_EXCLUSIVE;
+ }
+ table_name
+ {
+ LEX* lex= thd->lex;
+ DBUG_ASSERT(!lex->m_sql_cmd);
+ lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
+ if (lex->m_sql_cmd == NULL)
+ MYSQL_YYABORT;
+ }
+ opt_truncate_table_storage_clause { }
+ ;
+
+opt_truncate_table_storage_clause:
+ /* Empty */
+ | DROP STORAGE_SYM
+ | REUSE_SYM STORAGE_SYM
+ ;
+
+opt_table_sym:
+ /* empty */
+ | TABLE_SYM
+ ;
+
+opt_profile_defs:
+ /* empty */
+ | profile_defs;
+
+profile_defs:
+ profile_def
+ | profile_defs ',' profile_def;
+
+profile_def:
+ CPU_SYM
+ {
+ Lex->profile_options|= PROFILE_CPU;
+ }
+ | MEMORY_SYM
+ {
+ Lex->profile_options|= PROFILE_MEMORY;
+ }
+ | BLOCK_SYM IO_SYM
+ {
+ Lex->profile_options|= PROFILE_BLOCK_IO;
+ }
+ | CONTEXT_SYM SWITCHES_SYM
+ {
+ Lex->profile_options|= PROFILE_CONTEXT;
+ }
+ | PAGE_SYM FAULTS_SYM
+ {
+ Lex->profile_options|= PROFILE_PAGE_FAULTS;
+ }
+ | IPC_SYM
+ {
+ Lex->profile_options|= PROFILE_IPC;
+ }
+ | SWAPS_SYM
+ {
+ Lex->profile_options|= PROFILE_SWAPS;
+ }
+ | SOURCE_SYM
+ {
+ Lex->profile_options|= PROFILE_SOURCE;
+ }
+ | ALL
+ {
+ Lex->profile_options|= PROFILE_ALL;
+ }
+ ;
+
+opt_profile_args:
+ /* empty */
+ {
+ Lex->profile_query_id= 0;
+ }
+ | FOR_SYM QUERY_SYM NUM
+ {
+ Lex->profile_query_id= atoi($3.str);
+ }
+ ;
+
+/* Show things */
+
+show:
+ SHOW
+ {
+ LEX *lex=Lex;
+ lex->wild=0;
+ lex->ident= null_clex_str;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ lex->create_info.init();
+ }
+ show_param
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ ;
+
+show_param:
+ DATABASES wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_DATABASES;
+ if (prepare_schema_table(thd, lex, 0, SCH_SCHEMATA))
+ MYSQL_YYABORT;
+ }
+ | opt_full TABLES opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_TABLES;
+ lex->select_lex.db= $3.str;
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
+ MYSQL_YYABORT;
+ }
+ | opt_full TRIGGERS_SYM opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_TRIGGERS;
+ lex->select_lex.db= $3.str;
+ if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
+ MYSQL_YYABORT;
+ }
+ | EVENTS_SYM opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_EVENTS;
+ lex->select_lex.db= $2.str;
+ if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
+ MYSQL_YYABORT;
+ }
+ | TABLE_SYM STATUS_SYM opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
+ lex->select_lex.db= $3.str;
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
+ MYSQL_YYABORT;
+ }
+ | OPEN_SYM TABLES opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
+ lex->select_lex.db= $3.str;
+ if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
+ MYSQL_YYABORT;
+ }
+ | PLUGINS_SYM
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_PLUGINS;
+ if (prepare_schema_table(thd, lex, 0, SCH_PLUGINS))
+ MYSQL_YYABORT;
+ }
+ | PLUGINS_SYM SONAME_SYM TEXT_STRING_sys
+ {
+ Lex->ident= $3;
+ Lex->sql_command= SQLCOM_SHOW_PLUGINS;
+ if (prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS))
+ MYSQL_YYABORT;
+ }
+ | PLUGINS_SYM SONAME_SYM wild_and_where
+ {
+ Lex->sql_command= SQLCOM_SHOW_PLUGINS;
+ if (prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS))
+ MYSQL_YYABORT;
+ }
+ | ENGINE_SYM known_storage_engines show_engine_param
+ { Lex->create_info.db_type= $2; }
+ | ENGINE_SYM ALL show_engine_param
+ { Lex->create_info.db_type= NULL; }
+ | opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_FIELDS;
+ if ($5.str)
+ $4->change_db(&$5);
+ if (prepare_schema_table(thd, lex, $4, SCH_COLUMNS))
+ MYSQL_YYABORT;
+ }
+ | master_or_binary LOGS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_BINLOGS;
+ }
+ | SLAVE HOSTS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_HOSTS;
+ }
+ | BINLOG_SYM EVENTS_SYM binlog_in binlog_from
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
+ }
+ opt_limit_clause
+ | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS;
+ } opt_limit_clause
+ | keys_or_index from_or_in table_ident opt_db opt_where_clause
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_KEYS;
+ if ($4.str)
+ $3->change_db(&$4);
+ if (prepare_schema_table(thd, lex, $3, SCH_STATISTICS))
+ MYSQL_YYABORT;
+ }
+ | opt_storage ENGINES_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
+ if (prepare_schema_table(thd, lex, 0, SCH_ENGINES))
+ MYSQL_YYABORT;
+ }
+ | AUTHORS_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_AUTHORS;
+ }
+ | CONTRIBUTORS_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_CONTRIBUTORS;
+ }
+ | PRIVILEGES
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_PRIVILEGES;
+ }
+ | COUNT_SYM '(' '*' ')' WARNINGS
+ { (void) create_select_for_variable("warning_count"); }
+ | COUNT_SYM '(' '*' ')' ERRORS
+ { (void) create_select_for_variable("error_count"); }
+ | WARNINGS opt_limit_clause
+ { Lex->sql_command = SQLCOM_SHOW_WARNS;}
+ | ERRORS opt_limit_clause
+ { Lex->sql_command = SQLCOM_SHOW_ERRORS;}
+ | PROFILES_SYM
+ { Lex->sql_command = SQLCOM_SHOW_PROFILES; }
+ | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_PROFILE;
+ if (prepare_schema_table(thd, lex, NULL, SCH_PROFILES) != 0)
+ MYSQL_YYABORT;
+ }
+ | opt_var_type STATUS_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_STATUS;
+ lex->option_type= $1;
+ if (prepare_schema_table(thd, lex, 0, SCH_SESSION_STATUS))
+ MYSQL_YYABORT;
+ }
+ | opt_full PROCESSLIST_SYM
+ { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
+ | opt_var_type VARIABLES wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_VARIABLES;
+ lex->option_type= $1;
+ if (prepare_schema_table(thd, lex, 0, SCH_SESSION_VARIABLES))
+ MYSQL_YYABORT;
+ }
+ | charset wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_CHARSETS;
+ if (prepare_schema_table(thd, lex, 0, SCH_CHARSETS))
+ MYSQL_YYABORT;
+ }
+ | COLLATION_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_COLLATIONS;
+ if (prepare_schema_table(thd, lex, 0, SCH_COLLATIONS))
+ MYSQL_YYABORT;
+ }
+ | GRANTS
+ {
+ Lex->sql_command= SQLCOM_SHOW_GRANTS;
+ if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ Lex->grant_user->user= current_user_and_current_role;
+ }
+ | GRANTS FOR_SYM user_or_role clear_privileges
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_GRANTS;
+ lex->grant_user=$3;
+ }
+ | CREATE DATABASE opt_if_not_exists ident
+ {
+ Lex->set_command(SQLCOM_SHOW_CREATE_DB, $3);
+ Lex->name= $4;
+ }
+ | CREATE TABLE_SYM table_ident
+ {
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_SHOW_CREATE;
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0))
+ MYSQL_YYABORT;
+ lex->create_info.storage_media= HA_SM_DEFAULT;
+ }
+ | CREATE VIEW_SYM table_ident
+ {
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_SHOW_CREATE;
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+ MYSQL_YYABORT;
+ lex->table_type= TABLE_TYPE_VIEW;
+ }
+ | CREATE SEQUENCE_SYM table_ident
+ {
+ LEX *lex= Lex;
+ lex->sql_command = SQLCOM_SHOW_CREATE;
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+ MYSQL_YYABORT;
+ lex->table_type= TABLE_TYPE_SEQUENCE;
+ }
+ | MASTER_SYM STATUS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
+ }
+ | ALL SLAVES STATUS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ Lex->verbose= 1;
+ }
+ | SLAVE STATUS_SYM
+ {
+ LEX *lex= thd->lex;
+ lex->mi.connection_name= null_clex_str;
+ lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ lex->verbose= 0;
+ }
+ | SLAVE connection_name STATUS_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
+ Lex->verbose= 0;
+ }
+ | CREATE PROCEDURE_SYM sp_name
+ {
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
+ lex->spname= $3;
+ }
+ | CREATE FUNCTION_SYM sp_name
+ {
+ LEX *lex= Lex;
+
+ lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
+ lex->spname= $3;
+ }
+ | CREATE TRIGGER_SYM sp_name
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_CREATE_TRIGGER;
+ lex->spname= $3;
+ }
+ | CREATE USER_SYM
+ {
+ Lex->sql_command= SQLCOM_SHOW_CREATE_USER;
+ if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ Lex->grant_user->user= current_user;
+ }
+ | CREATE USER_SYM user
+ {
+ Lex->sql_command= SQLCOM_SHOW_CREATE_USER;
+ Lex->grant_user= $3;
+ }
+ | PROCEDURE_SYM STATUS_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_STATUS_PROC;
+ if (prepare_schema_table(thd, lex, 0, SCH_PROCEDURES))
+ MYSQL_YYABORT;
+ }
+ | FUNCTION_SYM STATUS_SYM wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SHOW_STATUS_FUNC;
+ if (prepare_schema_table(thd, lex, 0, SCH_PROCEDURES))
+ MYSQL_YYABORT;
+ }
+ | PROCEDURE_SYM CODE_SYM sp_name
+ {
+ Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
+ Lex->spname= $3;
+ }
+ | FUNCTION_SYM CODE_SYM sp_name
+ {
+ Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
+ Lex->spname= $3;
+ }
+ | CREATE EVENT_SYM sp_name
+ {
+ Lex->spname= $3;
+ Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
+ }
+ | describe_command FOR_SYM expr
+ {
+ Lex->sql_command= SQLCOM_SHOW_EXPLAIN;
+ if (prepare_schema_table(thd, Lex, 0, SCH_EXPLAIN))
+ MYSQL_YYABORT;
+ add_value_to_list(thd, $3);
+ }
+ | IDENT_sys remember_tok_start wild_and_where
+ {
+ LEX *lex= Lex;
+ bool in_plugin;
+ lex->sql_command= SQLCOM_SHOW_GENERIC;
+ ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str, &in_plugin);
+ if (!table || !table->old_format || !in_plugin)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, $2);
+ MYSQL_YYABORT;
+ }
+ if (lex->wild && table->idx_field1 < 0)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, $3);
+ MYSQL_YYABORT;
+ }
+ if (make_schema_select(thd, Lex->current_select, table))
+ MYSQL_YYABORT;
+ }
+ ;
+
+show_engine_param:
+ STATUS_SYM
+ { Lex->sql_command= SQLCOM_SHOW_ENGINE_STATUS; }
+ | MUTEX_SYM
+ { Lex->sql_command= SQLCOM_SHOW_ENGINE_MUTEX; }
+ | LOGS_SYM
+ { Lex->sql_command= SQLCOM_SHOW_ENGINE_LOGS; }
+ ;
+
+master_or_binary:
+ MASTER_SYM
+ | BINARY
+ ;
+
+opt_storage:
+ /* empty */
+ | STORAGE_SYM
+ ;
+
+opt_db:
+ /* empty */ { $$= null_clex_str; }
+ | from_or_in ident { $$= $2; }
+ ;
+
+opt_full:
+ /* empty */ { Lex->verbose=0; }
+ | FULL { Lex->verbose=1; }
+ ;
+
+from_or_in:
+ FROM
+ | IN_SYM
+ ;
+
+binlog_in:
+ /* empty */ { Lex->mi.log_file_name = 0; }
+ | IN_SYM TEXT_STRING_sys { Lex->mi.log_file_name = $2.str; }
+ ;
+
+binlog_from:
+ /* empty */ { Lex->mi.pos = 4; /* skip magic number */ }
+ | FROM ulonglong_num { Lex->mi.pos = $2; }
+ ;
+
+wild_and_where:
+ /* empty */ { $$= 0; }
+ | LIKE remember_tok_start TEXT_STRING_sys
+ {
+ Lex->wild= new (thd->mem_root) String($3.str, $3.length,
+ system_charset_info);
+ if (Lex->wild == NULL)
+ MYSQL_YYABORT;
+ $$= $2;
+ }
+ | WHERE remember_tok_start expr
+ {
+ Select->where= normalize_cond(thd, $3);
+ if ($3)
+ $3->top_level_item();
+ $$= $2;
+ }
+ ;
+
+/* A Oracle compatible synonym for show */
+describe:
+ describe_command table_ident
+ {
+ LEX *lex= Lex;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ lex->sql_command= SQLCOM_SHOW_FIELDS;
+ lex->select_lex.db= 0;
+ lex->verbose= 0;
+ if (prepare_schema_table(thd, lex, $2, SCH_COLUMNS))
+ MYSQL_YYABORT;
+ }
+ opt_describe_column
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ | describe_command opt_extended_describe
+ { Lex->describe|= DESCRIBE_NORMAL; }
+ explainable_command
+ {
+ LEX *lex=Lex;
+ lex->select_lex.options|= SELECT_DESCRIBE;
+ }
+ ;
+
+explainable_command:
+ select
+ | insert
+ | replace
+ | update
+ | delete
+ ;
+
+describe_command:
+ DESC
+ | DESCRIBE
+ ;
+
+analyze_stmt_command:
+ ANALYZE_SYM opt_format_json explainable_command
+ {
+ Lex->analyze_stmt= true;
+ }
+ ;
+
+opt_extended_describe:
+ EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
+ | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
+ | opt_format_json {}
+ ;
+
+opt_format_json:
+ /* empty */ {}
+ | FORMAT_SYM '=' ident_or_text
+ {
+ if (!my_strcasecmp(system_charset_info, $3.str, "JSON"))
+ Lex->explain_json= true;
+ else if (!my_strcasecmp(system_charset_info, $3.str, "TRADITIONAL"))
+ DBUG_ASSERT(Lex->explain_json==false);
+ else
+ my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str));
+ }
+ ;
+
+opt_describe_column:
+ /* empty */ {}
+ | text_string { Lex->wild= $1; }
+ | ident
+ {
+ Lex->wild= new (thd->mem_root) String((const char*) $1.str,
+ $1.length,
+ system_charset_info);
+ if (Lex->wild == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+/* flush things */
+
+flush:
+ FLUSH_SYM opt_no_write_to_binlog
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_FLUSH;
+ lex->type= 0;
+ lex->no_write_to_binlog= $2;
+ }
+ flush_options
+ {}
+ ;
+
+flush_options:
+ table_or_tables
+ {
+ Lex->type|= REFRESH_TABLES;
+ /*
+ Set type of metadata and table locks for
+ FLUSH TABLES table_list [WITH READ LOCK].
+ */
+ YYPS->m_lock_type= TL_READ_NO_INSERT;
+ YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO;
+ }
+ opt_table_list opt_flush_lock
+ {}
+ | flush_options_list
+ ;
+
+opt_flush_lock:
+ /* empty */ {}
+ | flush_lock
+ {
+ TABLE_LIST *tables= Lex->query_tables;
+ for (; tables; tables= tables->next_global)
+ {
+ tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
+ /* Don't try to flush views. */
+ tables->required_type= TABLE_TYPE_NORMAL;
+ /* Ignore temporary tables. */
+ tables->open_type= OT_BASE_ONLY;
+ }
+ }
+ ;
+
+flush_lock:
+ WITH READ_SYM LOCK_SYM optional_flush_tables_arguments
+ { Lex->type|= REFRESH_READ_LOCK | $4; }
+ | FOR_SYM
+ {
+ if (Lex->query_tables == NULL) // Table list can't be empty
+ {
+ thd->parse_error(ER_NO_TABLES_USED);
+ MYSQL_YYABORT;
+ }
+ Lex->type|= REFRESH_FOR_EXPORT;
+ } EXPORT_SYM {}
+ ;
+
+flush_options_list:
+ flush_options_list ',' flush_option
+ | flush_option
+ {}
+ ;
+
+flush_option:
+ ERROR_SYM LOGS_SYM
+ { Lex->type|= REFRESH_ERROR_LOG; }
+ | ENGINE_SYM LOGS_SYM
+ { Lex->type|= REFRESH_ENGINE_LOG; }
+ | GENERAL LOGS_SYM
+ { Lex->type|= REFRESH_GENERAL_LOG; }
+ | SLOW LOGS_SYM
+ { Lex->type|= REFRESH_SLOW_LOG; }
+ | BINARY LOGS_SYM
+ { Lex->type|= REFRESH_BINARY_LOG; }
+ | RELAY LOGS_SYM optional_connection_name
+ {
+ LEX *lex= Lex;
+ if (lex->type & REFRESH_RELAY_LOG)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS"));
+ lex->type|= REFRESH_RELAY_LOG;
+ lex->relay_log_connection_name= lex->mi.connection_name;
+ }
+ | QUERY_SYM CACHE_SYM
+ { Lex->type|= REFRESH_QUERY_CACHE_FREE; }
+ | HOSTS_SYM
+ { Lex->type|= REFRESH_HOSTS; }
+ | PRIVILEGES
+ { Lex->type|= REFRESH_GRANT; }
+ | LOGS_SYM
+ {
+ Lex->type|= REFRESH_LOG;
+ Lex->relay_log_connection_name= empty_clex_str;
+ }
+ | STATUS_SYM
+ { Lex->type|= REFRESH_STATUS; }
+ | SLAVE optional_connection_name
+ {
+ LEX *lex= Lex;
+ if (lex->type & REFRESH_SLAVE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE"));
+ lex->type|= REFRESH_SLAVE;
+ lex->reset_slave_info.all= false;
+ }
+ | MASTER_SYM
+ { Lex->type|= REFRESH_MASTER; }
+ | DES_KEY_FILE
+ { Lex->type|= REFRESH_DES_KEY_FILE; }
+ | RESOURCES
+ { Lex->type|= REFRESH_USER_RESOURCES; }
+ | IDENT_sys remember_tok_start
+ {
+ Lex->type|= REFRESH_GENERIC;
+ ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str);
+ if (!table || !table->reset_table)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, $2);
+ MYSQL_YYABORT;
+ }
+ Lex->view_list.push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ ;
+
+opt_table_list:
+ /* empty */ {}
+ | table_list {}
+ ;
+
+optional_flush_tables_arguments:
+ /* empty */ {$$= 0;}
+ | AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; }
+
+reset:
+ RESET_SYM
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_RESET; lex->type=0;
+ }
+ reset_options
+ {}
+ ;
+
+reset_options:
+ reset_options ',' reset_option
+ | reset_option
+ ;
+
+reset_option:
+ SLAVE { Lex->type|= REFRESH_SLAVE; }
+ optional_connection_name
+ slave_reset_options { }
+ | MASTER_SYM
+ {
+ Lex->type|= REFRESH_MASTER;
+ Lex->next_binlog_file_number= 0;
+ }
+ master_reset_options
+ | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;}
+ ;
+
+slave_reset_options:
+ /* empty */ { Lex->reset_slave_info.all= false; }
+ | ALL { Lex->reset_slave_info.all= true; }
+ ;
+
+master_reset_options:
+ /* empty */ {}
+ | TO_SYM ulong_num
+ {
+ Lex->next_binlog_file_number = $2;
+ }
+ ;
+
+purge:
+ PURGE
+ {
+ LEX *lex=Lex;
+ lex->type=0;
+ lex->sql_command = SQLCOM_PURGE;
+ }
+ purge_options
+ {}
+ ;
+
+purge_options:
+ master_or_binary LOGS_SYM purge_option
+ ;
+
+purge_option:
+ TO_SYM TEXT_STRING_sys
+ {
+ Lex->to_log = $2.str;
+ }
+ | BEFORE_SYM expr
+ {
+ LEX *lex= Lex;
+ lex->value_list.empty();
+ lex->value_list.push_front($2, thd->mem_root);
+ lex->sql_command= SQLCOM_PURGE_BEFORE;
+ }
+ ;
+
+/* kill threads */
+
+kill:
+ KILL_SYM
+ {
+ LEX *lex=Lex;
+ lex->value_list.empty();
+ lex->users_list.empty();
+ lex->sql_command= SQLCOM_KILL;
+ lex->kill_type= KILL_TYPE_ID;
+ }
+ kill_type kill_option kill_expr
+ {
+ Lex->kill_signal= (killed_state) ($3 | $4);
+ }
+ ;
+
+kill_type:
+ /* Empty */ { $$= (int) KILL_HARD_BIT; }
+ | HARD_SYM { $$= (int) KILL_HARD_BIT; }
+ | SOFT_SYM { $$= 0; }
+
+kill_option:
+ /* empty */ { $$= (int) KILL_CONNECTION; }
+ | CONNECTION_SYM { $$= (int) KILL_CONNECTION; }
+ | QUERY_SYM { $$= (int) KILL_QUERY; }
+ | QUERY_SYM ID_SYM
+ {
+ $$= (int) KILL_QUERY;
+ Lex->kill_type= KILL_TYPE_QUERY;
+ }
+ ;
+
+kill_expr:
+ expr
+ {
+ Lex->value_list.push_front($$, thd->mem_root);
+ }
+ | USER_SYM user
+ {
+ Lex->users_list.push_back($2, thd->mem_root);
+ Lex->kill_type= KILL_TYPE_USER;
+ }
+ ;
+
+
+shutdown:
+ SHUTDOWN { Lex->sql_command= SQLCOM_SHUTDOWN; }
+ ;
+
+/* change database */
+
+use:
+ USE_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command=SQLCOM_CHANGE_DB;
+ lex->select_lex.db= $2.str;
+ }
+ ;
+
+/* import, export of files */
+
+load:
+ LOAD data_or_xml
+ {
+ LEX *lex= thd->lex;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0),
+ $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
+ MYSQL_YYABORT;
+ }
+ }
+ load_data_lock opt_local INFILE TEXT_STRING_filesystem
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_LOAD;
+ lex->local_file= $5;
+ lex->duplicates= DUP_ERROR;
+ lex->ignore= 0;
+ if (!(lex->exchange= new (thd->mem_root) sql_exchange($7.str, 0, $2)))
+ MYSQL_YYABORT;
+ }
+ opt_duplicate INTO TABLE_SYM table_ident opt_use_partition
+ {
+ LEX *lex=Lex;
+ if (!Select->add_table_to_list(thd, $12, NULL, TL_OPTION_UPDATING,
+ $4, MDL_SHARED_WRITE, NULL, $13))
+ MYSQL_YYABORT;
+ lex->field_list.empty();
+ lex->update_list.empty();
+ lex->value_list.empty();
+ }
+ opt_load_data_charset
+ { Lex->exchange->cs= $15; }
+ opt_xml_rows_identified_by
+ opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
+ opt_load_data_set_spec
+ {}
+ ;
+
+data_or_xml:
+ DATA_SYM { $$= FILETYPE_CSV; }
+ | XML_SYM { $$= FILETYPE_XML; }
+ ;
+
+opt_local:
+ /* empty */ { $$=0;}
+ | LOCAL_SYM { $$=1;}
+ ;
+
+load_data_lock:
+ /* empty */ { $$= TL_WRITE_DEFAULT; }
+ | CONCURRENT
+ {
+ /*
+ Ignore this option in SP to avoid problem with query cache and
+ triggers with non default priority locks
+ */
+ $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
+ }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
+ ;
+
+opt_duplicate:
+ /* empty */ { Lex->duplicates=DUP_ERROR; }
+ | REPLACE { Lex->duplicates=DUP_REPLACE; }
+ | IGNORE_SYM { Lex->ignore= 1; }
+ ;
+
+opt_field_term:
+ /* empty */
+ | COLUMNS field_term_list
+ ;
+
+field_term_list:
+ field_term_list field_term
+ | field_term
+ ;
+
+field_term:
+ TERMINATED BY text_string
+ {
+ DBUG_ASSERT(Lex->exchange != 0);
+ Lex->exchange->field_term= $3;
+ }
+ | OPTIONALLY ENCLOSED BY text_string
+ {
+ LEX *lex= Lex;
+ DBUG_ASSERT(lex->exchange != 0);
+ lex->exchange->enclosed= $4;
+ lex->exchange->opt_enclosed= 1;
+ }
+ | ENCLOSED BY text_string
+ {
+ DBUG_ASSERT(Lex->exchange != 0);
+ Lex->exchange->enclosed= $3;
+ }
+ | ESCAPED BY text_string
+ {
+ DBUG_ASSERT(Lex->exchange != 0);
+ Lex->exchange->escaped= $3;
+ }
+ ;
+
+opt_line_term:
+ /* empty */
+ | LINES line_term_list
+ ;
+
+line_term_list:
+ line_term_list line_term
+ | line_term
+ ;
+
+line_term:
+ TERMINATED BY text_string
+ {
+ DBUG_ASSERT(Lex->exchange != 0);
+ Lex->exchange->line_term= $3;
+ }
+ | STARTING BY text_string
+ {
+ DBUG_ASSERT(Lex->exchange != 0);
+ Lex->exchange->line_start= $3;
+ }
+ ;
+
+opt_xml_rows_identified_by:
+ /* empty */ { }
+ | ROWS_SYM IDENTIFIED_SYM BY text_string
+ { Lex->exchange->line_term = $4; };
+
+opt_ignore_lines:
+ /* empty */
+ | IGNORE_SYM NUM lines_or_rows
+ {
+ DBUG_ASSERT(Lex->exchange != 0);
+ Lex->exchange->skip_lines= atol($2.str);
+ }
+ ;
+
+lines_or_rows:
+ LINES { }
+ | ROWS_SYM { }
+ ;
+
+opt_field_or_var_spec:
+ /* empty */ {}
+ | '(' fields_or_vars ')' {}
+ | '(' ')' {}
+ ;
+
+fields_or_vars:
+ fields_or_vars ',' field_or_var
+ { Lex->field_list.push_back($3, thd->mem_root); }
+ | field_or_var
+ { Lex->field_list.push_back($1, thd->mem_root); }
+ ;
+
+field_or_var:
+ simple_ident_nospvar {$$= $1;}
+ | '@' ident_or_text
+ {
+ $$= new (thd->mem_root) Item_user_var_as_out_param(thd, &$2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+opt_load_data_set_spec:
+ /* empty */ {}
+ | SET load_data_set_list {}
+ ;
+
+load_data_set_list:
+ load_data_set_list ',' load_data_set_elem
+ | load_data_set_elem
+ ;
+
+load_data_set_elem:
+ simple_ident_nospvar equal remember_name expr_or_default remember_end
+ {
+ LEX *lex= Lex;
+ if (lex->update_list.push_back($1, thd->mem_root) ||
+ lex->value_list.push_back($4, thd->mem_root))
+ MYSQL_YYABORT;
+ $4->set_name_no_truncate(thd, $3, (uint) ($5 - $3), thd->charset());
+ }
+ ;
+
+/* Common definitions */
+
+text_literal:
+ TEXT_STRING
+ {
+ if (!($$= thd->make_string_literal($1)))
+ MYSQL_YYABORT;
+ }
+ | NCHAR_STRING
+ {
+ DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
+ $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
+ national_charset_info,
+ DERIVATION_COERCIBLE,
+ $1.repertoire());
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | UNDERSCORE_CHARSET TEXT_STRING
+ {
+ $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str,
+ $2.length, $1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | text_literal TEXT_STRING_literal
+ {
+ Item_string* item= (Item_string*) $1;
+ item->append($2.str, $2.length);
+ if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
+ {
+ /*
+ If the string has been pure ASCII so far,
+ check the new part.
+ */
+ CHARSET_INFO *cs= thd->variables.collation_connection;
+ item->collation.repertoire|= my_string_repertoire(cs,
+ $2.str,
+ $2.length);
+ }
+ }
+ ;
+
+text_string:
+ TEXT_STRING_literal
+ {
+ $$= new (thd->mem_root) String($1.str,
+ $1.length,
+ thd->variables.collation_connection);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | hex_or_bin_String { $$= $1; }
+ ;
+
+
+hex_or_bin_String:
+ HEX_NUM
+ {
+ Item *tmp= new (thd->mem_root) Item_hex_hybrid(thd, $1.str,
+ $1.length);
+ if (tmp == NULL)
+ MYSQL_YYABORT;
+ /*
+ it is OK only emulate fix_fields, because we need only
+ value of constant
+ */
+ tmp->quick_fix_field();
+ $$= tmp->val_str((String*) 0);
+ }
+ | HEX_STRING
+ {
+ Item *tmp= new (thd->mem_root) Item_hex_string(thd, $1.str,
+ $1.length);
+ if (tmp == NULL)
+ MYSQL_YYABORT;
+ tmp->quick_fix_field();
+ $$= tmp->val_str((String*) 0);
+ }
+ | BIN_NUM
+ {
+ Item *tmp= new (thd->mem_root) Item_bin_string(thd, $1.str,
+ $1.length);
+ if (tmp == NULL)
+ MYSQL_YYABORT;
+ /*
+ it is OK only emulate fix_fields, because we need only
+ value of constant
+ */
+ tmp->quick_fix_field();
+ $$= tmp->val_str((String*) 0);
+ }
+ ;
+
+param_marker:
+ PARAM_MARKER
+ {
+ if (!($$= Lex->add_placeholder(thd, &param_clex_str,
+ YYLIP->get_tok_start(),
+ YYLIP->get_tok_start() + 1)))
+ MYSQL_YYABORT;
+ }
+ | colon_with_pos ident
+ {
+ if (!($$= Lex->add_placeholder(thd, &null_clex_str,
+ $1, YYLIP->get_tok_end())))
+ MYSQL_YYABORT;
+ }
+ | colon_with_pos NUM
+ {
+ if (!($$= Lex->add_placeholder(thd, &null_clex_str,
+ $1, YYLIP->get_ptr())))
+ MYSQL_YYABORT;
+ }
+ ;
+
+signed_literal:
+ '+' NUM_literal { $$ = $2; }
+ | '-' NUM_literal
+ {
+ $2->max_length++;
+ $$= $2->neg(thd);
+ }
+ ;
+
+literal:
+ text_literal { $$ = $1; }
+ | NUM_literal { $$ = $1; }
+ | temporal_literal { $$= $1; }
+ | NULL_SYM
+ {
+ /*
+ For the digest computation, in this context only,
+ NULL is considered a literal, hence reduced to '?'
+ REDUCE:
+ TOK_GENERIC_VALUE := NULL_SYM
+ */
+ YYLIP->reduce_digest_token(TOK_GENERIC_VALUE, NULL_SYM);
+ $$= new (thd->mem_root) Item_null(thd);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT;
+ }
+ | FALSE_SYM
+ {
+ $$= new (thd->mem_root) Item_bool(thd, (char*) "FALSE",0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | TRUE_SYM
+ {
+ $$= new (thd->mem_root) Item_bool(thd, (char*) "TRUE",1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | HEX_NUM
+ {
+ $$= new (thd->mem_root) Item_hex_hybrid(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | HEX_STRING
+ {
+ $$= new (thd->mem_root) Item_hex_string(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | BIN_NUM
+ {
+ $$= new (thd->mem_root) Item_bin_string(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | UNDERSCORE_CHARSET hex_or_bin_String
+ {
+ Item_string_with_introducer *item_str;
+ /*
+ Pass NULL as name. Name will be set in the "select_item" rule and
+ will include the introducer and the original hex/bin notation.
+ */
+ item_str= new (thd->mem_root)
+ Item_string_with_introducer(thd, NULL, $2->ptr(), $2->length(),
+ $1);
+ if (!item_str || !item_str->check_well_formed_result(true))
+ MYSQL_YYABORT;
+
+ $$= item_str;
+ }
+ ;
+
+NUM_literal:
+ NUM
+ {
+ int error;
+ $$= new (thd->mem_root)
+ Item_int(thd, $1.str,
+ (longlong) my_strtoll10($1.str, NULL, &error),
+ $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | LONG_NUM
+ {
+ int error;
+ $$= new (thd->mem_root)
+ Item_int(thd, $1.str,
+ (longlong) my_strtoll10($1.str, NULL, &error),
+ $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ULONGLONG_NUM
+ {
+ $$= new (thd->mem_root) Item_uint(thd, $1.str, $1.length);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DECIMAL_NUM
+ {
+ $$= new (thd->mem_root) Item_decimal(thd, $1.str, $1.length,
+ thd->charset());
+ if (($$ == NULL) || (thd->is_error()))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ | FLOAT_NUM
+ {
+ $$= new (thd->mem_root) Item_float(thd, $1.str, $1.length);
+ if (($$ == NULL) || (thd->is_error()))
+ {
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+
+temporal_literal:
+ DATE_SYM TEXT_STRING
+ {
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
+ MYSQL_TYPE_DATE, true)))
+ MYSQL_YYABORT;
+ }
+ | TIME_SYM TEXT_STRING
+ {
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
+ MYSQL_TYPE_TIME, true)))
+ MYSQL_YYABORT;
+ }
+ | TIMESTAMP TEXT_STRING
+ {
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
+ MYSQL_TYPE_DATETIME, true)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+opt_with_clause:
+ /*empty */ { $$= 0; }
+ | with_clause
+ {
+ $$= $1;
+ }
+ ;
+
+
+with_clause:
+ WITH opt_recursive
+ {
+ With_clause *with_clause=
+ new With_clause($2, Lex->curr_with_clause);
+ if (with_clause == NULL)
+ MYSQL_YYABORT;
+ Lex->derived_tables|= DERIVED_WITH;
+ Lex->curr_with_clause= with_clause;
+ with_clause->add_to_list(Lex->with_clauses_list_last_next);
+ }
+ with_list
+ {
+ $$= Lex->curr_with_clause;
+ Lex->curr_with_clause= Lex->curr_with_clause->pop();
+ }
+ ;
+
+
+opt_recursive:
+ /*empty*/ { $$= 0; }
+ | RECURSIVE_SYM { $$= 1; }
+ ;
+
+
+with_list:
+ with_list_element
+ | with_list ',' with_list_element
+ ;
+
+
+with_list_element:
+ query_name
+ opt_with_column_list
+ {
+ $2= new List<LEX_CSTRING> (Lex->with_column_list);
+ if ($2 == NULL)
+ MYSQL_YYABORT;
+ Lex->with_column_list.empty();
+ }
+ AS '(' remember_name subselect remember_end ')'
+ {
+ With_element *elem= new With_element($1, *$2, $7->master_unit());
+ if (elem == NULL || Lex->curr_with_clause->add_with_element(elem))
+ MYSQL_YYABORT;
+ if (elem->set_unparsed_spec(thd, $6+1, $8))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+opt_with_column_list:
+ /* empty */
+ { $$= NULL; }
+ | '(' with_column_list ')'
+ { $$= NULL; }
+ ;
+
+
+with_column_list:
+ ident
+ {
+ Lex->with_column_list.push_back((LEX_CSTRING*)
+ thd->memdup(&$1, sizeof(LEX_CSTRING)));
+ }
+ | with_column_list ',' ident
+ {
+ Lex->with_column_list.push_back((LEX_CSTRING*)
+ thd->memdup(&$3, sizeof(LEX_CSTRING)));
+ }
+ ;
+
+
+query_name:
+ ident
+ {
+ $$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+
+/**********************************************************************
+** Creating different items.
+**********************************************************************/
+
+insert_ident:
+ simple_ident_nospvar { $$=$1; }
+ | table_wild { $$=$1; }
+ ;
+
+table_wild:
+ ident '.' '*'
+ {
+ SELECT_LEX *sel= Select;
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
+ NullS, $1.str, &star_clex_str);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ sel->with_wild++;
+ }
+ | ident '.' ident '.' '*'
+ {
+ SELECT_LEX *sel= Select;
+ const char* schema= thd->client_capabilities & CLIENT_NO_SCHEMA ?
+ NullS : $1.str;
+ $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
+ schema,
+ $3.str, &star_clex_str);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ sel->with_wild++;
+ }
+ ;
+
+order_ident:
+ expr { $$=$1; }
+ ;
+
+simple_ident:
+ ident
+ {
+ Lex_input_stream *lip= YYLIP;
+ if (!($$= Lex->create_item_ident(thd, &$1,
+ lip->get_tok_start_prev(),
+ lip->get_tok_end())))
+ MYSQL_YYABORT;
+ }
+ | simple_ident_q2
+ | ident '.' ident
+ {
+ LEX *lex= thd->lex;
+ if (!($$= lex->create_item_ident(thd, &$1, &$3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ YYLIP->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+simple_ident_nospvar:
+ ident
+ {
+ if (!($$= Lex->create_item_ident_nosp(thd, &$1)))
+ MYSQL_YYABORT;
+ }
+ | simple_ident_q { $$= $1; }
+ ;
+
+simple_ident_q:
+ ident '.' ident
+ {
+ if (!($$= Lex->create_item_ident_nospvar(thd, &$1, &$3)))
+ MYSQL_YYABORT;
+ }
+ | simple_ident_q2
+ ;
+
+simple_ident_q2:
+ colon_with_pos ident '.' ident
+ {
+ LEX *lex= Lex;
+ if (lex->is_trigger_new_or_old_reference(&$2))
+ {
+ bool new_row= ($2.str[0]=='N' || $2.str[0]=='n');
+ if (!($$= Lex->create_and_link_Item_trigger_field(thd,
+ &$4,
+ new_row)))
+ MYSQL_YYABORT;
+ }
+ else
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ | '.' ident '.' ident
+ {
+ if (!($$= Lex->create_item_ident(thd, &null_clex_str, &$2, &$4)))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident '.' ident
+ {
+ if (!($$= Lex->create_item_ident(thd, &$1, &$3, &$5)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+field_ident:
+ ident { $$=$1;}
+ | ident '.' ident '.' ident
+ {
+ TABLE_LIST *table= Select->table_list.first;
+ if (my_strcasecmp(table_alias_charset, $1.str, table->db))
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
+ if (my_strcasecmp(table_alias_charset, $3.str,
+ table->table_name))
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3.str));
+ $$=$5;
+ }
+ | ident '.' ident
+ {
+ TABLE_LIST *table= Select->table_list.first;
+ if (my_strcasecmp(table_alias_charset, $1.str, table->alias))
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $1.str));
+ $$=$3;
+ }
+ | '.' ident { $$=$2;} /* For Delphi */
+ ;
+
+table_ident:
+ ident
+ {
+ $$= new (thd->mem_root) Table_ident(&$1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident
+ {
+ $$= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | '.' ident
+ {
+ /* For Delphi */
+ $$= new (thd->mem_root) Table_ident(&$2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+table_ident_opt_wild:
+ ident opt_wild
+ {
+ $$= new (thd->mem_root) Table_ident(&$1);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident opt_wild
+ {
+ $$= new (thd->mem_root) Table_ident(thd, &$1, &$3, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+table_ident_nodb:
+ ident
+ {
+ LEX_CSTRING db={(char*) any_db,3};
+ $$= new (thd->mem_root) Table_ident(thd, &db, &$1, 0);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+IDENT_sys:
+ IDENT { $$= $1; }
+ | IDENT_QUOTED
+ {
+ if (thd->charset_is_system_charset)
+ {
+ CHARSET_INFO *cs= system_charset_info;
+ uint wlen= Well_formed_prefix(cs, $1.str, $1.length).length();
+ if (wlen < $1.length)
+ {
+ ErrConvString err($1.str, $1.length, &my_charset_bin);
+ my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
+ cs->csname, err.ptr());
+ MYSQL_YYABORT;
+ }
+ $$= $1;
+ }
+ else
+ {
+ LEX_STRING to;
+ if (thd->convert_with_error(system_charset_info, &to,
+ thd->charset(), $1.str, $1.length))
+ MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
+ }
+ }
+ ;
+
+TEXT_STRING_sys:
+ TEXT_STRING
+ {
+ if (thd->charset_is_system_charset)
+ $$= $1;
+ else
+ {
+ LEX_STRING to;
+ if (thd->convert_string(&to, system_charset_info,
+ $1.str, $1.length, thd->charset()))
+ MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
+ }
+ }
+ ;
+
+TEXT_STRING_literal:
+ TEXT_STRING
+ {
+ if (thd->charset_is_collation_connection)
+ $$= $1;
+ else
+ {
+ LEX_STRING to;
+ if (thd->convert_string(&to, thd->variables.collation_connection,
+ $1.str, $1.length, thd->charset()))
+ MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
+ }
+ }
+ ;
+
+TEXT_STRING_filesystem:
+ TEXT_STRING
+ {
+ if (thd->charset_is_character_set_filesystem)
+ $$= $1;
+ else
+ {
+ LEX_STRING to;
+ if (thd->convert_string(&to,
+ thd->variables.character_set_filesystem,
+ $1.str, $1.length, thd->charset()))
+ MYSQL_YYABORT;
+ $$.str= to.str;
+ $$.length= to.length;
+ }
+ }
+ ;
+
+ident:
+ IDENT_sys
+ {
+ (LEX_CSTRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
+ | keyword
+ {
+ $$.str= thd->strmake($1.str, $1.length);
+ if ($$.str == NULL)
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
+ ;
+
+ident_with_tok_start:
+ IDENT_sys
+ {
+ (LEX_CSTRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
+ }
+ | keyword
+ {
+ if (!($$.str= thd->strmake($1.str, $1.length)))
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
+ }
+ ;
+
+ident_directly_assignable:
+ IDENT_sys { $$=$1; }
+ | keyword_directly_assignable
+ {
+ $$.str= thd->strmake($1.str, $1.length);
+ if ($$.str == NULL)
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ }
+ | keyword_sp
+ {
+ $$.str= thd->strmake($1.str, $1.length);
+ if ($$.str == NULL)
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ }
+ ;
+
+
+label_ident:
+ IDENT_sys { $$=$1; }
+ | keyword_sp
+ {
+ $$.str= thd->strmake($1.str, $1.length);
+ if ($$.str == NULL)
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ }
+ ;
+
+labels_declaration_oracle:
+ label_declaration_oracle { $$= $1; }
+ | labels_declaration_oracle label_declaration_oracle { $$= $2; }
+ ;
+
+label_declaration_oracle:
+ SHIFT_LEFT label_ident SHIFT_RIGHT
+ {
+ if (Lex->sp_push_goto_label(thd, &$2))
+ MYSQL_YYABORT;
+ $$= $2;
+ }
+ ;
+
+ident_or_text:
+ ident { $$=$1;}
+ | TEXT_STRING_sys { $$=$1;}
+ | LEX_HOSTNAME { $$=$1;}
+ ;
+
+user_maybe_role:
+ ident_or_text
+ {
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user = $1;
+ $$->host= null_clex_str; // User or Role, see get_current_user()
+ $$->reset_auth();
+
+ if (check_string_char_length(&$$->user, ER_USERNAME,
+ username_char_length,
+ system_charset_info, 0))
+ MYSQL_YYABORT;
+ }
+ | ident_or_text '@' ident_or_text
+ {
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user = $1; $$->host=$3;
+ $$->reset_auth();
+
+ if (check_string_char_length(&$$->user, ER_USERNAME,
+ username_char_length,
+ system_charset_info, 0) ||
+ check_host_name(&$$->host))
+ MYSQL_YYABORT;
+ if ($$->host.str[0])
+ {
+ /*
+ Convert hostname part of username to lowercase.
+ It's OK to use in-place lowercase as long as
+ the character set is utf8.
+ */
+ my_casedn_str(system_charset_info, (char*) $$->host.str);
+ }
+ else
+ {
+ /*
+ fix historical undocumented convention that empty host is the
+ same as '%'
+ */
+ $$->host= host_not_specified;
+ }
+ }
+ | CURRENT_USER optional_braces
+ {
+ if (!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user= current_user;
+ $$->plugin= empty_clex_str;
+ $$->auth= empty_clex_str;
+ }
+ ;
+
+user_or_role: user_maybe_role | current_role;
+
+user: user_maybe_role
+ {
+ if ($1->user.str != current_user.str && $1->host.str == 0)
+ $1->host= host_not_specified;
+ $$= $1;
+ }
+ ;
+
+/* Keyword that we allow for identifiers (except SP labels) */
+keyword:
+ keyword_sp {}
+ | keyword_directly_assignable {}
+ | keyword_directly_not_assignable {}
+ ;
+
+
+/*
+ Keywords that we allow in Oracle-style direct assignments:
+ xxx := 10;
+*/
+keyword_directly_assignable:
+ ASCII_SYM {}
+ | BACKUP_SYM {}
+ | BINLOG_SYM {}
+ | BYTE_SYM {}
+ | CACHE_SYM {}
+ | CHECKSUM_SYM {}
+ | CHECKPOINT_SYM {}
+ | COLUMN_ADD_SYM {}
+ | COLUMN_CHECK_SYM {}
+ | COLUMN_CREATE_SYM {}
+ | COLUMN_DELETE_SYM {}
+ | COLUMN_GET_SYM {}
+ | DEALLOCATE_SYM {}
+ | EXAMINED_SYM {}
+ | EXCLUDE_SYM {}
+ | EXECUTE_SYM {}
+ | FLUSH_SYM {}
+ | FOLLOWING_SYM {}
+ | FORMAT_SYM {}
+ | GET_SYM {}
+ | HELP_SYM {}
+ | HOST_SYM {}
+ | INSTALL_SYM {}
+ | OPTION {}
+ | OPTIONS_SYM {}
+ | OWNER_SYM {}
+ | PARSER_SYM {}
+ | PORT_SYM {}
+ | PRECEDING_SYM {}
+ | PREPARE_SYM {}
+ | REMOVE_SYM {}
+ | RESET_SYM {}
+ | RESTORE_SYM {}
+ | SECURITY_SYM {}
+ | SERVER_SYM {}
+ | SIGNED_SYM {}
+ | SOCKET_SYM {}
+ | SLAVE {}
+ | SLAVES {}
+ | SONAME_SYM {}
+ | START_SYM {}
+ | STOP_SYM {}
+ | STORED_SYM {}
+ | TIES_SYM {}
+ | UNICODE_SYM {}
+ | UNINSTALL_SYM {}
+ | UNBOUNDED_SYM {}
+ | WRAPPER_SYM {}
+ | XA_SYM {}
+ | UPGRADE_SYM {}
+ ;
+
+/*
+ Keywords that are allowed as identifiers (e.g. table, column names),
+ but:
+ - not allowed as SP label names
+ - not allowed as variable names in Oracle-style assignments:
+ xxx := 10;
+
+ If we allowed these variables in assignments, there would be conflicts
+ with SP characteristics, or verb clauses, or compound statements, e.g.:
+ CREATE PROCEDURE p1 LANGUAGE ...
+ would be either:
+ CREATE PROCEDURE p1 LANGUAGE SQL BEGIN END;
+ or
+ CREATE PROCEDURE p1 LANGUAGE:=10;
+
+ Note, these variables can still be assigned using quoted identifiers:
+ `do`:= 10;
+ "do":= 10; (when ANSI_QUOTES)
+ or using a SET statement:
+ SET do= 10;
+
+ Note, some of these keywords are reserved keywords in Oracle.
+ In case if heavy grammar conflicts are found in the future,
+ we'll possibly need to make them reserved for sql_mode=ORACLE.
+
+ TODO: Allow these variables as SP lables when sql_mode=ORACLE.
+ TODO: Allow assigning of "SP characteristics" marked variables
+ inside compound blocks.
+ TODO: Allow "follows" and "precedes" as variables in compound blocks:
+ BEGIN
+ follows := 10;
+ END;
+ as they conflict only with non-block FOR EACH ROW statement:
+ CREATE TRIGGER .. FOR EACH ROW follows:= 10;
+ CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10;
+*/
+keyword_directly_not_assignable:
+ CONTAINS_SYM { /* SP characteristic */ }
+ | LANGUAGE_SYM { /* SP characteristic */ }
+ | NO_SYM { /* SP characteristic */ }
+ | CHARSET { /* SET CHARSET utf8; */ }
+ | FOLLOWS_SYM { /* Conflicts with assignment in FOR EACH */}
+ | PRECEDES_SYM { /* Conflicts with assignment in FOR EACH */}
+ | keyword_sp_verb_clause { }
+ ;
+
+/*
+ * Keywords that we allow for labels in SPs.
+ * Anything that's the beginning of a statement or characteristics
+ * must be in keyword above, otherwise we get (harmful) shift/reduce
+ * conflicts.
+ */
+keyword_sp:
+ keyword_sp_data_type
+ | keyword_sp_not_data_type
+ ;
+
+
+/*
+ Keywords that start a statement.
+ Generally allowed as identifiers (e.g. table, column names)
+ - not allowed as SP label names
+ - not allowed as variable names in Oracle-style assignments:
+ xxx:=10
+*/
+keyword_sp_verb_clause:
+ BEGIN_SYM { /* Compound. Reserved in Oracle */ }
+ | CLOSE_SYM { /* Verb clause. Reserved in Oracle */ }
+ | COMMIT_SYM { /* Verb clause. Reserved in Oracle */ }
+ | DO_SYM { /* Verb clause */ }
+ | END { /* Compound. Reserved in Oracle */ }
+ | HANDLER_SYM { /* Verb clause */ }
+ | OPEN_SYM { /* Verb clause. Reserved in Oracle */ }
+ | REPAIR { /* Verb clause */ }
+ | ROLLBACK_SYM { /* Verb clause. Reserved in Oracle */ }
+ | SAVEPOINT_SYM { /* Verb clause. Reserved in Oracle */ }
+ | SHUTDOWN { /* Verb clause */ }
+ | TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
+ ;
+
+
+/*
+ These keywords are generally allowed as identifiers,
+ but not allowed as non-delimited SP variable names in sql_mode=ORACLE.
+*/
+keyword_sp_data_type:
+ BIT_SYM {}
+ | BOOLEAN_SYM {} /* PLSQL-R */
+ | BOOL_SYM {}
+ | CLOB {}
+ | DATE_SYM {} /* Oracle-R, PLSQL-R */
+ | DATETIME {}
+ | ENUM {}
+ | FIXED_SYM {}
+ | GEOMETRYCOLLECTION {}
+ | GEOMETRY_SYM {}
+ | JSON_SYM {}
+ | LINESTRING {}
+ | MEDIUM_SYM {}
+ | MULTILINESTRING {}
+ | MULTIPOINT {}
+ | MULTIPOLYGON {}
+ | NATIONAL_SYM {}
+ | NCHAR_SYM {}
+ | NUMBER_SYM {} /* Oracle-R, PLSQL-R */
+ | NVARCHAR_SYM {}
+ | POINT_SYM {}
+ | POLYGON {}
+ | RAW {} /* Oracle-R */
+ | ROW_SYM {}
+ | SERIAL_SYM {}
+ | TEXT_SYM {}
+ | TIMESTAMP {}
+ | TIME_SYM {} /* Oracle-R */
+ | VARCHAR2 {} /* Oracle-R, PLSQL-R */
+ | YEAR_SYM {}
+ ;
+
+
+keyword_sp_not_data_type:
+ ACTION {}
+ | ADDDATE_SYM {}
+ | ADMIN_SYM {}
+ | AFTER_SYM {}
+ | AGAINST {}
+ | AGGREGATE_SYM {}
+ | ALGORITHM_SYM {}
+ | ALWAYS_SYM {}
+ | ANY_SYM {}
+ | AT_SYM {}
+ | ATOMIC_SYM {}
+ | AUTHORS_SYM {}
+ | AUTO_INC {}
+ | AUTOEXTEND_SIZE_SYM {}
+ | AUTO_SYM {}
+ | AVG_ROW_LENGTH {}
+ | AVG_SYM {}
+ | BLOCK_SYM {}
+ | BTREE_SYM {}
+ | CASCADED {}
+ | CATALOG_NAME_SYM {}
+ | CHAIN_SYM {}
+ | CHANGED {}
+ | CIPHER_SYM {}
+ | CLIENT_SYM {}
+ | CLASS_ORIGIN_SYM {}
+ | COALESCE {}
+ | CODE_SYM {}
+ | COLLATION_SYM {}
+ | COLUMN_NAME_SYM {}
+ | COLUMNS {}
+ | COMMITTED_SYM {}
+ | COMPACT_SYM {}
+ | COMPLETION_SYM {}
+ | COMPRESSED_SYM {}
+ | CONCURRENT {}
+ | CONNECTION_SYM {}
+ | CONSISTENT_SYM {}
+ | CONSTRAINT_CATALOG_SYM {}
+ | CONSTRAINT_SCHEMA_SYM {}
+ | CONSTRAINT_NAME_SYM {}
+ | CONTEXT_SYM {}
+ | CONTRIBUTORS_SYM {}
+ | CURRENT_POS_SYM {}
+ | CPU_SYM {}
+ | CUBE_SYM {}
+ /*
+ Although a reserved keyword in SQL:2003 (and :2008),
+ not reserved in MySQL per WL#2111 specification.
+ */
+ | CURRENT_SYM {}
+ | CURSOR_NAME_SYM {}
+ | CYCLE_SYM {}
+ | DATA_SYM {}
+ | DATAFILE_SYM {}
+ | DAY_SYM {}
+ | DECODE_SYM {}
+ | DEFINER_SYM {}
+ | DELAY_KEY_WRITE_SYM {}
+ | DES_KEY_FILE {}
+ | DIAGNOSTICS_SYM {}
+ | DIRECTORY_SYM {}
+ | DISABLE_SYM {}
+ | DISCARD {}
+ | DISK_SYM {}
+ | DUMPFILE {}
+ | DUPLICATE_SYM {}
+ | DYNAMIC_SYM {}
+ | ENDS_SYM {}
+ | ENGINE_SYM {}
+ | ENGINES_SYM {}
+ | ERROR_SYM {}
+ | ERRORS {}
+ | ESCAPE_SYM {}
+ | EVENT_SYM {}
+ | EVENTS_SYM {}
+ | EVERY_SYM {}
+ | EXCHANGE_SYM {}
+ | EXPANSION_SYM {}
+ | EXPORT_SYM {}
+ | EXTENDED_SYM {}
+ | EXTENT_SIZE_SYM {}
+ | FAULTS_SYM {}
+ | FAST_SYM {}
+ | FOUND_SYM {}
+ | ENABLE_SYM {}
+ | FULL {}
+ | FILE_SYM {}
+ | FIRST_SYM {}
+ | GENERAL {}
+ | GENERATED_SYM {}
+ | GET_FORMAT {}
+ | GRANTS {}
+ | GLOBAL_SYM {}
+ | HASH_SYM {}
+ | HARD_SYM {}
+ | HOSTS_SYM {}
+ | HOUR_SYM {}
+ | ID_SYM {}
+ | IDENTIFIED_SYM {}
+ | IGNORE_SERVER_IDS_SYM {}
+ | INCREMENT_SYM {}
+ | IMMEDIATE_SYM {} /* SQL-2003-R */
+ | INVOKER_SYM {}
+ | IMPORT {}
+ | INDEXES {}
+ | INITIAL_SIZE_SYM {}
+ | IO_SYM {}
+ | IPC_SYM {}
+ | ISOLATION {}
+ | ISOPEN_SYM {}
+ | ISSUER_SYM {}
+ | INSERT_METHOD {}
+ | KEY_BLOCK_SIZE {}
+ | LAST_VALUE {}
+ | LAST_SYM {}
+ | LASTVAL_SYM {}
+ | LEAVES {}
+ | LESS_SYM {}
+ | LEVEL_SYM {}
+ | LIST_SYM {}
+ | LOCAL_SYM {}
+ | LOCKS_SYM {}
+ | LOGFILE_SYM {}
+ | LOGS_SYM {}
+ | MAX_ROWS {}
+ | MASTER_SYM {}
+ | MASTER_HEARTBEAT_PERIOD_SYM {}
+ | MASTER_GTID_POS_SYM {}
+ | MASTER_HOST_SYM {}
+ | MASTER_PORT_SYM {}
+ | MASTER_LOG_FILE_SYM {}
+ | MASTER_LOG_POS_SYM {}
+ | MASTER_USER_SYM {}
+ | MASTER_USE_GTID_SYM {}
+ | MASTER_PASSWORD_SYM {}
+ | MASTER_SERVER_ID_SYM {}
+ | MASTER_CONNECT_RETRY_SYM {}
+ | MASTER_DELAY_SYM {}
+ | MASTER_SSL_SYM {}
+ | MASTER_SSL_CA_SYM {}
+ | MASTER_SSL_CAPATH_SYM {}
+ | MASTER_SSL_CERT_SYM {}
+ | MASTER_SSL_CIPHER_SYM {}
+ | MASTER_SSL_CRL_SYM {}
+ | MASTER_SSL_CRLPATH_SYM {}
+ | MASTER_SSL_KEY_SYM {}
+ | MAX_CONNECTIONS_PER_HOUR {}
+ | MAX_QUERIES_PER_HOUR {}
+ | MAX_SIZE_SYM {}
+ | MAX_STATEMENT_TIME_SYM {}
+ | MAX_UPDATES_PER_HOUR {}
+ | MAX_USER_CONNECTIONS_SYM {}
+ | MEMORY_SYM {}
+ | MERGE_SYM {}
+ | MESSAGE_TEXT_SYM {}
+ | MICROSECOND_SYM {}
+ | MIGRATE_SYM {}
+ | MINUTE_SYM {}
+ | MINVALUE_SYM {}
+ | MIN_ROWS {}
+ | MODIFY_SYM {}
+ | MODE_SYM {}
+ | MONTH_SYM {}
+ | MUTEX_SYM {}
+ | MYSQL_SYM {}
+ | MYSQL_ERRNO_SYM {}
+ | NAME_SYM {}
+ | NAMES_SYM {}
+ | NEXT_SYM {}
+ | NEXTVAL_SYM {}
+ | NEW_SYM {}
+ | NOCACHE_SYM {}
+ | NOCYCLE_SYM {}
+ | NOMINVALUE_SYM {}
+ | NOMAXVALUE_SYM {}
+ | NO_WAIT_SYM {}
+ | NODEGROUP_SYM {}
+ | NONE_SYM {}
+ | NOTFOUND_SYM {}
+ | OF_SYM {} /* SQL-1999-R, Oracle-R */
+ | OFFSET_SYM {}
+ | OLD_PASSWORD_SYM {}
+ | ONE_SYM {}
+ | ONLINE_SYM {}
+ | ONLY_SYM {}
+ | PACK_KEYS_SYM {}
+ | PAGE_SYM {}
+ | PARTIAL {}
+ | PARTITIONING_SYM {}
+ | PARTITIONS_SYM {}
+ | PASSWORD_SYM {}
+ | PERSISTENT_SYM {}
+ | PHASE_SYM {}
+ | PLUGIN_SYM {}
+ | PLUGINS_SYM {}
+ | PRESERVE_SYM {}
+ | PREV_SYM {}
+ | PREVIOUS_SYM {}
+ | PRIVILEGES {}
+ | PROCESS {}
+ | PROCESSLIST_SYM {}
+ | PROFILE_SYM {}
+ | PROFILES_SYM {}
+ | PROXY_SYM {}
+ | QUARTER_SYM {}
+ | QUERY_SYM {}
+ | QUICK {}
+ | READ_ONLY_SYM {}
+ | REBUILD_SYM {}
+ | RECOVER_SYM {}
+ | REDO_BUFFER_SIZE_SYM {}
+ | REDOFILE_SYM {}
+ | REDUNDANT_SYM {}
+ | RELAY {}
+ | RELAYLOG_SYM {}
+ | RELAY_LOG_FILE_SYM {}
+ | RELAY_LOG_POS_SYM {}
+ | RELAY_THREAD {}
+ | RELOAD {}
+ | REORGANIZE_SYM {}
+ | REPEATABLE_SYM {}
+ | REPLICATION {}
+ | RESOURCES {}
+ | RESTART_SYM {}
+ | RESUME_SYM {}
+ | RETURNED_SQLSTATE_SYM {}
+ | RETURNS_SYM {}
+ | REUSE_SYM {} /* Oracle-R */
+ | REVERSE_SYM {}
+ | ROLE_SYM {}
+ | ROLLUP_SYM {}
+ | ROUTINE_SYM {}
+ | ROWCOUNT_SYM {}
+ | ROW_COUNT_SYM {}
+ | ROW_FORMAT_SYM {}
+ | RTREE_SYM {}
+ | SCHEDULE_SYM {}
+ | SCHEMA_NAME_SYM {}
+ | SECOND_SYM {}
+ | SEQUENCE_SYM {}
+ | SERIALIZABLE_SYM {}
+ | SESSION_SYM {}
+ | SETVAL_SYM {}
+ | SIMPLE_SYM {}
+ | SHARE_SYM {}
+ | SLAVE_POS_SYM {}
+ | SLOW {}
+ | SNAPSHOT_SYM {}
+ | SOFT_SYM {}
+ | SOUNDS_SYM {}
+ | SOURCE_SYM {}
+ | SQL_CACHE_SYM {}
+ | SQL_BUFFER_RESULT {}
+ | SQL_NO_CACHE_SYM {}
+ | SQL_THREAD {}
+ | STARTS_SYM {}
+ | STATEMENT_SYM {}
+ | STATUS_SYM {}
+ | STORAGE_SYM {}
+ | STRING_SYM {}
+ | SUBCLASS_ORIGIN_SYM {}
+ | SUBDATE_SYM {}
+ | SUBJECT_SYM {}
+ | SUBPARTITION_SYM {}
+ | SUBPARTITIONS_SYM {}
+ | SUPER_SYM {}
+ | SUSPEND_SYM {}
+ | SWAPS_SYM {}
+ | SWITCHES_SYM {}
+ | TABLE_NAME_SYM {}
+ | TABLES {}
+ | TABLE_CHECKSUM_SYM {}
+ | TABLESPACE {}
+ | TEMPORARY {}
+ | TEMPTABLE_SYM {}
+ | THAN_SYM {}
+ | TRANSACTION_SYM {}
+ | TRANSACTIONAL_SYM {}
+ | TRIGGERS_SYM {}
+ | TIMESTAMP_ADD {}
+ | TIMESTAMP_DIFF {}
+ | TYPES_SYM {}
+ | TYPE_SYM {}
+ | UDF_RETURNS_SYM {}
+ | FUNCTION_SYM {}
+ | UNCOMMITTED_SYM {}
+ | UNDEFINED_SYM {}
+ | UNDO_BUFFER_SIZE_SYM {}
+ | UNDOFILE_SYM {}
+ | UNKNOWN_SYM {}
+ | UNTIL_SYM {}
+ | USER_SYM {}
+ | USE_FRM {}
+ | VARIABLES {}
+ | VIEW_SYM {}
+ | VIRTUAL_SYM {}
+ | VALUE_SYM {}
+ | WARNINGS {}
+ | WAIT_SYM {}
+ | WEEK_SYM {}
+ | WEIGHT_STRING_SYM {}
+ | WORK_SYM {}
+ | X509_SYM {}
+ | XML_SYM {}
+ | VIA_SYM {}
+ ;
+
+/*
+ SQLCOM_SET_OPTION statement.
+
+ Note that to avoid shift/reduce conflicts, we have separate rules for the
+ first option listed in the statement.
+*/
+
+set:
+ SET
+ {
+ LEX *lex=Lex;
+ lex->set_stmt_init();
+ lex->var_list.empty();
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ start_option_value_list
+ {}
+ | SET STATEMENT_SYM
+ {
+ Lex->set_stmt_init();
+ }
+ set_stmt_option_value_following_option_type_list
+ {
+ LEX *lex= Lex;
+ if (lex->table_or_sp_used())
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
+ lex->stmt_var_list= lex->var_list;
+ lex->var_list.empty();
+ }
+ FOR_SYM verb_clause
+ {}
+ ;
+
+set_assign:
+ internal_variable_name_directly_assignable SET_VAR
+ {
+ LEX *lex=Lex;
+ lex->set_stmt_init();
+ lex->var_list.empty();
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ set_expr_or_default
+ {
+ if (Lex->set_variable(&$1, $4) ||
+ sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | ident_directly_assignable '.' ident SET_VAR
+ {
+ LEX *lex=Lex;
+ lex->set_stmt_init();
+ lex->var_list.empty();
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ set_expr_or_default
+ {
+ LEX *lex= Lex;
+ DBUG_ASSERT(lex->var_list.is_empty());
+ if (lex->set_variable(&$1, &$3, $6) ||
+ lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
+ ;
+
+set_stmt_option_value_following_option_type_list:
+ /*
+ Only system variables can be used here. If this condition is changed
+ please check careful code under lex->option_type == OPT_STATEMENT
+ condition on wrong type casts.
+ */
+ option_value_following_option_type
+ | set_stmt_option_value_following_option_type_list ',' option_value_following_option_type
+ ;
+
+/* Start of option value list */
+start_option_value_list:
+ option_value_no_option_type
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ option_value_list_continued
+ | TRANSACTION_SYM
+ {
+ Lex->option_type= OPT_DEFAULT;
+ }
+ transaction_characteristics
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | option_type
+ {
+ Lex->option_type= $1;
+ }
+ start_option_value_list_following_option_type
+ ;
+
+
+/* Start of option value list, option_type was given */
+start_option_value_list_following_option_type:
+ option_value_following_option_type
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ option_value_list_continued
+ | TRANSACTION_SYM transaction_characteristics
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/* Remainder of the option value list after first option value. */
+option_value_list_continued:
+ /* empty */
+ | ',' option_value_list
+ ;
+
+/* Repeating list of option values after first option value. */
+option_value_list:
+ {
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ option_value
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | option_value_list ','
+ {
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ option_value
+ {
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/* Wrapper around option values following the first option value in the stmt. */
+option_value:
+ option_type
+ {
+ Lex->option_type= $1;
+ }
+ option_value_following_option_type
+ | option_value_no_option_type
+ ;
+
+option_type:
+ GLOBAL_SYM { $$=OPT_GLOBAL; }
+ | LOCAL_SYM { $$=OPT_SESSION; }
+ | SESSION_SYM { $$=OPT_SESSION; }
+ ;
+
+opt_var_type:
+ /* empty */ { $$=OPT_SESSION; }
+ | GLOBAL_SYM { $$=OPT_GLOBAL; }
+ | LOCAL_SYM { $$=OPT_SESSION; }
+ | SESSION_SYM { $$=OPT_SESSION; }
+ ;
+
+opt_var_ident_type:
+ /* empty */ { $$=OPT_DEFAULT; }
+ | GLOBAL_SYM '.' { $$=OPT_GLOBAL; }
+ | LOCAL_SYM '.' { $$=OPT_SESSION; }
+ | SESSION_SYM '.' { $$=OPT_SESSION; }
+ ;
+
+/* Option values with preceding option_type. */
+option_value_following_option_type:
+ internal_variable_name equal set_expr_or_default
+ {
+ LEX *lex= Lex;
+
+ if ($1.var && $1.var != trg_new_row_fake_var)
+ {
+ /* It is a system variable. */
+ if (lex->set_system_variable(&$1, lex->option_type, $3))
+ MYSQL_YYABORT;
+ }
+ else
+ {
+ /*
+ Not in trigger assigning value to new row,
+ and option_type preceding local variable is illegal.
+ */
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+/* Option values without preceding option_type. */
+option_value_no_option_type:
+ ident equal set_expr_or_default
+ {
+ struct sys_var_with_base var;
+ if (Lex->init_internal_variable(&var, &$1) ||
+ Lex->set_variable(&var, $3))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident equal set_expr_or_default
+ {
+ DBUG_ASSERT(Lex->var_list.is_empty());
+ if (Lex->set_variable(&$1, &$3, $5))
+ MYSQL_YYABORT;
+ }
+ | DEFAULT '.' ident equal set_expr_or_default
+ {
+ struct sys_var_with_base var;
+ if (Lex->init_default_internal_variable(&var, $3) ||
+ Lex->set_variable(&var, $5))
+ MYSQL_YYABORT;
+ }
+ | '@' ident_or_text equal expr
+ {
+ Item_func_set_user_var *item;
+ item= new (thd->mem_root) Item_func_set_user_var(thd, &$2, $4);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var_user *var= new (thd->mem_root) set_var_user(item);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ Lex->var_list.push_back(var, thd->mem_root);
+ }
+ | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
+ {
+ struct sys_var_with_base tmp= $4;
+ /* Lookup if necessary: must be a system variable. */
+ if (tmp.var == NULL)
+ {
+ if (find_sys_var_null_base(thd, &tmp))
+ MYSQL_YYABORT;
+ }
+ if (Lex->set_system_variable(&tmp, $3, $6))
+ MYSQL_YYABORT;
+ }
+ | charset old_or_new_charset_name_or_default
+ {
+ LEX *lex= thd->lex;
+ CHARSET_INFO *cs2;
+ cs2= $2 ? $2: global_system_variables.character_set_client;
+ set_var_collation_client *var;
+ var= (new (thd->mem_root)
+ set_var_collation_client(cs2,
+ thd->variables.collation_database,
+ cs2));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ | NAMES_SYM equal expr
+ {
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+ LEX_CSTRING names= { STRING_WITH_LEN("names") };
+ if (spc && spc->find_variable(&names, false))
+ my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
+ else
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ | NAMES_SYM charset_name_or_default opt_collate
+ {
+ LEX *lex= Lex;
+ CHARSET_INFO *cs2;
+ CHARSET_INFO *cs3;
+ cs2= $2 ? $2 : global_system_variables.character_set_client;
+ cs3= $3 ? $3 : cs2;
+ if (!my_charset_same(cs2, cs3))
+ {
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ cs3->name, cs2->csname);
+ MYSQL_YYABORT;
+ }
+ set_var_collation_client *var;
+ var= new (thd->mem_root) set_var_collation_client(cs3, cs3, cs3);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ | DEFAULT ROLE_SYM grant_role
+ {
+ LEX *lex = Lex;
+ LEX_USER *user;
+ if (!(user=(LEX_USER *) thd->calloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ user->user= current_user;
+ set_var_default_role *var= (new (thd->mem_root)
+ set_var_default_role(user,
+ $3->user));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ thd->lex->autocommit= TRUE;
+ if (lex->sphead)
+ lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ }
+ | DEFAULT ROLE_SYM grant_role FOR_SYM user
+ {
+ LEX *lex = Lex;
+ set_var_default_role *var= (new (thd->mem_root)
+ set_var_default_role($5, $3->user));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ thd->lex->autocommit= TRUE;
+ if (lex->sphead)
+ lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ }
+ | ROLE_SYM ident_or_text
+ {
+ LEX *lex = Lex;
+ set_var_role *var= new (thd->mem_root) set_var_role($2);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ | PASSWORD_SYM opt_for_user text_or_password
+ {
+ LEX *lex = Lex;
+ set_var_password *var= (new (thd->mem_root)
+ set_var_password(lex->definer));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ lex->autocommit= TRUE;
+ if (lex->sphead)
+ lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
+ }
+ ;
+
+
+internal_variable_name:
+ ident
+ {
+ if (Lex->init_internal_variable(&$$, &$1))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident
+ {
+ if (Lex->init_internal_variable(&$$, &$1, &$3))
+ MYSQL_YYABORT;
+ }
+ | DEFAULT '.' ident
+ {
+ if (Lex->init_default_internal_variable(&$$, $3))
+ MYSQL_YYABORT;
+ }
+ ;
+
+
+internal_variable_name_directly_assignable:
+ ident_directly_assignable
+ {
+ if (Lex->init_internal_variable(&$$, &$1))
+ MYSQL_YYABORT;
+ }
+ | DEFAULT '.' ident
+ {
+ if (Lex->init_default_internal_variable(&$$, $3))
+ MYSQL_YYABORT;
+ }
+ | colon_with_pos ident_directly_assignable '.' ident
+ {
+ if (!Lex->is_trigger_new_or_old_reference(&$2))
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ if (Lex->init_internal_variable(&$$, &$2, &$4))
+ MYSQL_YYABORT;
+ }
+ ;
+
+transaction_characteristics:
+ transaction_access_mode
+ | isolation_level
+ | transaction_access_mode ',' isolation_level
+ | isolation_level ',' transaction_access_mode
+ ;
+
+transaction_access_mode:
+ transaction_access_mode_types
+ {
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) $1);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= (new (thd->mem_root)
+ set_var(thd, lex->option_type,
+ find_sys_var(thd, "tx_read_only"),
+ &null_clex_str,
+ item));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ ;
+
+isolation_level:
+ ISOLATION LEVEL_SYM isolation_types
+ {
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) $3);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= (new (thd->mem_root)
+ set_var(thd, lex->option_type,
+ find_sys_var(thd, "tx_isolation"),
+ &null_clex_str,
+ item));
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var, thd->mem_root);
+ }
+ ;
+
+transaction_access_mode_types:
+ READ_SYM ONLY_SYM { $$= true; }
+ | READ_SYM WRITE_SYM { $$= false; }
+ ;
+
+isolation_types:
+ READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
+ | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
+ | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; }
+ | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; }
+ ;
+
+opt_for_user:
+ equal
+ {
+ LEX *lex= thd->lex;
+ sp_pcontext *spc= lex->spcont;
+ LEX_CSTRING pw= { STRING_WITH_LEN("password") };
+
+ if (spc && spc->find_variable(&pw, false))
+ my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
+ if (!(lex->definer= (LEX_USER*) thd->calloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ lex->definer->user= current_user;
+ lex->definer->plugin= empty_clex_str;
+ lex->definer->auth= empty_clex_str;
+ }
+ | FOR_SYM user equal { Lex->definer= $2; }
+ ;
+
+text_or_password:
+ TEXT_STRING { Lex->definer->pwhash= $1;}
+ | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; }
+ | OLD_PASSWORD_SYM '(' TEXT_STRING ')'
+ {
+ Lex->definer->pwtext= $3;
+ Lex->definer->pwhash.str= Item_func_password::alloc(thd,
+ $3.str, $3.length, Item_func_password::OLD);
+ Lex->definer->pwhash.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ }
+ ;
+
+set_expr_or_default:
+ expr { $$=$1; }
+ | DEFAULT { $$=0; }
+ | ON
+ {
+ $$=new (thd->mem_root) Item_string_sys(thd, "ON", 2);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | ALL
+ {
+ $$=new (thd->mem_root) Item_string_sys(thd, "ALL", 3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | BINARY
+ {
+ $$=new (thd->mem_root) Item_string_sys(thd, "binary", 6);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+/* Lock function */
+
+lock:
+ LOCK_SYM table_or_tables
+ {
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
+ lex->sql_command= SQLCOM_LOCK_TABLES;
+ }
+ table_lock_list
+ {}
+ ;
+
+table_or_tables:
+ TABLE_SYM { }
+ | TABLES { }
+ ;
+
+table_lock_list:
+ table_lock
+ | table_lock_list ',' table_lock
+ ;
+
+table_lock:
+ table_ident opt_table_alias lock_option
+ {
+ thr_lock_type lock_type= (thr_lock_type) $3;
+ bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
+ if (!Select->add_table_to_list(thd, $1, $2, 0, lock_type,
+ (lock_for_write ?
+ lock_type == TL_WRITE_CONCURRENT_INSERT ?
+ MDL_SHARED_WRITE :
+ MDL_SHARED_NO_READ_WRITE :
+ MDL_SHARED_READ)))
+ MYSQL_YYABORT;
+ }
+ ;
+
+lock_option:
+ READ_SYM { $$= TL_READ_NO_INSERT; }
+ | WRITE_SYM { $$= TL_WRITE_DEFAULT; }
+ | WRITE_SYM CONCURRENT
+ {
+ $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
+ }
+
+ | LOW_PRIORITY WRITE_SYM { $$= TL_WRITE_LOW_PRIORITY; }
+ | READ_SYM LOCAL_SYM { $$= TL_READ; }
+ ;
+
+unlock:
+ UNLOCK_SYM
+ {
+ LEX *lex= Lex;
+
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
+ lex->sql_command= SQLCOM_UNLOCK_TABLES;
+ }
+ table_or_tables
+ {}
+ ;
+
+/*
+** Handler: direct access to ISAM functions
+*/
+
+handler:
+ HANDLER_SYM table_ident OPEN_SYM opt_table_alias
+ {
+ LEX *lex= Lex;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
+ lex->sql_command = SQLCOM_HA_OPEN;
+ if (!lex->current_select->add_table_to_list(thd, $2, $4, 0))
+ MYSQL_YYABORT;
+ }
+ | HANDLER_SYM table_ident_nodb CLOSE_SYM
+ {
+ LEX *lex= Lex;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
+ lex->sql_command = SQLCOM_HA_CLOSE;
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
+ MYSQL_YYABORT;
+ }
+ | HANDLER_SYM table_ident_nodb READ_SYM
+ {
+ LEX *lex=Lex;
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
+ lex->expr_allows_subselect= FALSE;
+ lex->sql_command = SQLCOM_HA_READ;
+ lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
+ Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
+ if (one == NULL)
+ MYSQL_YYABORT;
+ lex->current_select->select_limit= one;
+ lex->current_select->offset_limit= 0;
+ lex->limit_rows_examined= 0;
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
+ MYSQL_YYABORT;
+ }
+ handler_read_or_scan opt_where_clause opt_limit_clause
+ {
+ Lex->expr_allows_subselect= TRUE;
+ /* Stored functions are not supported for HANDLER READ. */
+ if (Lex->uses_stored_routines())
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "stored functions in HANDLER ... READ");
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+handler_read_or_scan:
+ handler_scan_function { Lex->ident= null_clex_str; }
+ | ident handler_rkey_function { Lex->ident= $1; }
+ ;
+
+handler_scan_function:
+ FIRST_SYM { Lex->ha_read_mode = RFIRST; }
+ | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
+ ;
+
+handler_rkey_function:
+ FIRST_SYM { Lex->ha_read_mode = RFIRST; }
+ | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
+ | PREV_SYM { Lex->ha_read_mode = RPREV; }
+ | LAST_SYM { Lex->ha_read_mode = RLAST; }
+ | handler_rkey_mode
+ {
+ LEX *lex=Lex;
+ lex->ha_read_mode = RKEY;
+ lex->ha_rkey_mode=$1;
+ if (!(lex->insert_list= new (thd->mem_root) List_item))
+ MYSQL_YYABORT;
+ }
+ '(' values ')'
+ {}
+ ;
+
+handler_rkey_mode:
+ '=' { $$=HA_READ_KEY_EXACT; }
+ | GE { $$=HA_READ_KEY_OR_NEXT; }
+ | LE { $$=HA_READ_KEY_OR_PREV; }
+ | '>' { $$=HA_READ_AFTER_KEY; }
+ | '<' { $$=HA_READ_BEFORE_KEY; }
+ ;
+
+/* GRANT / REVOKE */
+
+revoke:
+ REVOKE clear_privileges revoke_command
+ {}
+ ;
+
+revoke_command:
+ grant_privileges ON opt_table grant_ident FROM user_and_role_list
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= 0;
+ }
+ | grant_privileges ON FUNCTION_SYM grant_ident FROM user_and_role_list
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= TYPE_ENUM_FUNCTION;
+ }
+ | grant_privileges ON PROCEDURE_SYM grant_ident FROM user_and_role_list
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= TYPE_ENUM_PROCEDURE;
+ }
+ | ALL opt_privileges ',' GRANT OPTION FROM user_and_role_list
+ {
+ Lex->sql_command = SQLCOM_REVOKE_ALL;
+ }
+ | PROXY_SYM ON user FROM user_list
+ {
+ LEX *lex= Lex;
+ lex->users_list.push_front ($3);
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= TYPE_ENUM_PROXY;
+ }
+ | admin_option_for_role FROM user_and_role_list
+ {
+ Lex->sql_command= SQLCOM_REVOKE_ROLE;
+ if (Lex->users_list.push_front($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+admin_option_for_role:
+ ADMIN_SYM OPTION FOR_SYM grant_role
+ { Lex->with_admin_option= true; $$= $4; }
+ | grant_role
+ { Lex->with_admin_option= false; $$= $1; }
+ ;
+
+grant:
+ GRANT clear_privileges grant_command
+ {}
+ ;
+
+grant_command:
+ grant_privileges ON opt_table grant_ident TO_SYM grant_list
+ opt_require_clause opt_grant_options
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= 0;
+ }
+ | grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
+ opt_require_clause opt_grant_options
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= TYPE_ENUM_FUNCTION;
+ }
+ | grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list
+ opt_require_clause opt_grant_options
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= TYPE_ENUM_PROCEDURE;
+ }
+ | PROXY_SYM ON user TO_SYM grant_list opt_grant_option
+ {
+ LEX *lex= Lex;
+ lex->users_list.push_front ($3);
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= TYPE_ENUM_PROXY;
+ }
+ | grant_role TO_SYM grant_list opt_with_admin_option
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_GRANT_ROLE;
+ /* The first role is the one that is granted */
+ if (Lex->users_list.push_front($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+
+ ;
+
+opt_with_admin:
+ /* nothing */ { Lex->definer = 0; }
+ | WITH ADMIN_SYM user_or_role { Lex->definer = $3; }
+
+opt_with_admin_option:
+ /* nothing */ { Lex->with_admin_option= false; }
+ | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; }
+
+role_list:
+ grant_role
+ {
+ if (Lex->users_list.push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | role_list ',' grant_role
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+current_role:
+ CURRENT_ROLE optional_braces
+ {
+ if (!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user= current_role;
+ $$->reset_auth();
+ }
+ ;
+
+grant_role:
+ ident_or_text
+ {
+ CHARSET_INFO *cs= system_charset_info;
+ /* trim end spaces (as they'll be lost in mysql.user anyway) */
+ $1.length= cs->cset->lengthsp(cs, $1.str, $1.length);
+ ((char*) $1.str)[$1.length] = '\0';
+ if ($1.length == 0)
+ my_yyabort_error((ER_INVALID_ROLE, MYF(0), ""));
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ MYSQL_YYABORT;
+ $$->user= $1;
+ $$->host= empty_clex_str;
+ $$->reset_auth();
+
+ if (check_string_char_length(&$$->user, ER_USERNAME,
+ username_char_length,
+ cs, 0))
+ MYSQL_YYABORT;
+ }
+ | current_role
+ ;
+
+opt_table:
+ /* Empty */
+ | TABLE_SYM
+ ;
+
+grant_privileges:
+ object_privilege_list {}
+ | ALL opt_privileges
+ {
+ Lex->all_privileges= 1;
+ Lex->grant= GLOBAL_ACLS;
+ }
+ ;
+
+opt_privileges:
+ /* empty */
+ | PRIVILEGES
+ ;
+
+object_privilege_list:
+ object_privilege
+ | object_privilege_list ',' object_privilege
+ ;
+
+object_privilege:
+ SELECT_SYM
+ { Lex->which_columns = SELECT_ACL;}
+ opt_column_list {}
+ | INSERT
+ { Lex->which_columns = INSERT_ACL;}
+ opt_column_list {}
+ | UPDATE_SYM
+ { Lex->which_columns = UPDATE_ACL; }
+ opt_column_list {}
+ | REFERENCES
+ { Lex->which_columns = REFERENCES_ACL;}
+ opt_column_list {}
+ | DELETE_SYM { Lex->grant |= DELETE_ACL;}
+ | USAGE {}
+ | INDEX_SYM { Lex->grant |= INDEX_ACL;}
+ | ALTER { Lex->grant |= ALTER_ACL;}
+ | CREATE { Lex->grant |= CREATE_ACL;}
+ | DROP { Lex->grant |= DROP_ACL;}
+ | EXECUTE_SYM { Lex->grant |= EXECUTE_ACL;}
+ | RELOAD { Lex->grant |= RELOAD_ACL;}
+ | SHUTDOWN { Lex->grant |= SHUTDOWN_ACL;}
+ | PROCESS { Lex->grant |= PROCESS_ACL;}
+ | FILE_SYM { Lex->grant |= FILE_ACL;}
+ | GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ | SHOW DATABASES { Lex->grant |= SHOW_DB_ACL;}
+ | SUPER_SYM { Lex->grant |= SUPER_ACL;}
+ | CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;}
+ | LOCK_SYM TABLES { Lex->grant |= LOCK_TABLES_ACL; }
+ | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL; }
+ | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL; }
+ | CREATE VIEW_SYM { Lex->grant |= CREATE_VIEW_ACL; }
+ | SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
+ | CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
+ | ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
+ | CREATE USER_SYM { Lex->grant |= CREATE_USER_ACL; }
+ | EVENT_SYM { Lex->grant |= EVENT_ACL;}
+ | TRIGGER_SYM { Lex->grant |= TRIGGER_ACL; }
+ | CREATE TABLESPACE { Lex->grant |= CREATE_TABLESPACE_ACL; }
+ ;
+
+opt_and:
+ /* empty */ {}
+ | AND_SYM {}
+ ;
+
+require_list:
+ require_list_element opt_and require_list
+ | require_list_element
+ ;
+
+require_list_element:
+ SUBJECT_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->x509_subject)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT"));
+ lex->x509_subject=$2.str;
+ }
+ | ISSUER_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->x509_issuer)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER"));
+ lex->x509_issuer=$2.str;
+ }
+ | CIPHER_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->ssl_cipher)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER"));
+ lex->ssl_cipher=$2.str;
+ }
+ ;
+
+grant_ident:
+ '*'
+ {
+ LEX *lex= Lex;
+ size_t dummy;
+ if (lex->copy_db_to(&lex->current_select->db, &dummy))
+ MYSQL_YYABORT;
+ if (lex->grant == GLOBAL_ACLS)
+ lex->grant = DB_ACLS & ~GRANT_ACL;
+ else if (lex->columns.elements)
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
+ }
+ | ident '.' '*'
+ {
+ LEX *lex= Lex;
+ lex->current_select->db = $1.str;
+ if (lex->grant == GLOBAL_ACLS)
+ lex->grant = DB_ACLS & ~GRANT_ACL;
+ else if (lex->columns.elements)
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
+ }
+ | '*' '.' '*'
+ {
+ LEX *lex= Lex;
+ lex->current_select->db = NULL;
+ if (lex->grant == GLOBAL_ACLS)
+ lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
+ else if (lex->columns.elements)
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
+ }
+ | table_ident
+ {
+ LEX *lex=Lex;
+ if (!lex->current_select->add_table_to_list(thd, $1,NULL,
+ TL_OPTION_UPDATING))
+ MYSQL_YYABORT;
+ if (lex->grant == GLOBAL_ACLS)
+ lex->grant = TABLE_ACLS & ~GRANT_ACL;
+ }
+ ;
+
+user_list:
+ user
+ {
+ if (Lex->users_list.push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | user_list ',' user
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+grant_list:
+ grant_user
+ {
+ if (Lex->users_list.push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | grant_list ',' grant_user
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+user_and_role_list:
+ user_or_role
+ {
+ if (Lex->users_list.push_back($1, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ | user_and_role_list ',' user_or_role
+ {
+ if (Lex->users_list.push_back($3, thd->mem_root))
+ MYSQL_YYABORT;
+ }
+ ;
+
+via_or_with: VIA_SYM | WITH ;
+using_or_as: USING | AS ;
+
+grant_user:
+ user IDENTIFIED_SYM BY TEXT_STRING
+ {
+ $$= $1;
+ $1->pwtext= $4;
+ if (Lex->sql_command == SQLCOM_REVOKE)
+ MYSQL_YYABORT;
+ }
+ | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING
+ {
+ $$= $1;
+ $1->pwhash= $5;
+ }
+ | user IDENTIFIED_SYM via_or_with ident_or_text
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= empty_clex_str;
+ }
+ | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as TEXT_STRING_sys
+ {
+ $$= $1;
+ $1->plugin= $4;
+ $1->auth= $6;
+ }
+ | user_or_role
+ { $$= $1; }
+ ;
+
+opt_column_list:
+ /* empty */
+ {
+ LEX *lex=Lex;
+ lex->grant |= lex->which_columns;
+ }
+ | '(' column_list ')'
+ ;
+
+column_list:
+ column_list ',' column_list_id
+ | column_list_id
+ ;
+
+column_list_id:
+ ident
+ {
+ String *new_str= new (thd->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
+ if (new_str == NULL)
+ MYSQL_YYABORT;
+ List_iterator <LEX_COLUMN> iter(Lex->columns);
+ class LEX_COLUMN *point;
+ LEX *lex=Lex;
+ while ((point=iter++))
+ {
+ if (!my_strcasecmp(system_charset_info,
+ point->column.c_ptr(), new_str->c_ptr()))
+ break;
+ }
+ lex->grant_tot_col|= lex->which_columns;
+ if (point)
+ point->rights |= lex->which_columns;
+ else
+ {
+ LEX_COLUMN *col= (new (thd->mem_root)
+ LEX_COLUMN(*new_str,lex->which_columns));
+ if (col == NULL)
+ MYSQL_YYABORT;
+ lex->columns.push_back(col, thd->mem_root);
+ }
+ }
+ ;
+
+opt_require_clause:
+ /* empty */
+ | REQUIRE_SYM require_list
+ {
+ Lex->ssl_type=SSL_TYPE_SPECIFIED;
+ }
+ | REQUIRE_SYM SSL_SYM
+ {
+ Lex->ssl_type=SSL_TYPE_ANY;
+ }
+ | REQUIRE_SYM X509_SYM
+ {
+ Lex->ssl_type=SSL_TYPE_X509;
+ }
+ | REQUIRE_SYM NONE_SYM
+ {
+ Lex->ssl_type=SSL_TYPE_NONE;
+ }
+ ;
+
+resource_option:
+ MAX_QUERIES_PER_HOUR ulong_num
+ {
+ LEX *lex=Lex;
+ lex->mqh.questions=$2;
+ lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR;
+ }
+ | MAX_UPDATES_PER_HOUR ulong_num
+ {
+ LEX *lex=Lex;
+ lex->mqh.updates=$2;
+ lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR;
+ }
+ | MAX_CONNECTIONS_PER_HOUR ulong_num
+ {
+ LEX *lex=Lex;
+ lex->mqh.conn_per_hour= $2;
+ lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
+ }
+ | MAX_USER_CONNECTIONS_SYM int_num
+ {
+ LEX *lex=Lex;
+ lex->mqh.user_conn= $2;
+ lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS;
+ }
+ | MAX_STATEMENT_TIME_SYM NUM_literal
+ {
+ LEX *lex=Lex;
+ lex->mqh.max_statement_time= $2->val_real();
+ lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME;
+ }
+ ;
+
+resource_option_list:
+ resource_option_list resource_option {}
+ | resource_option {}
+ ;
+
+opt_resource_options:
+ /* empty */ {}
+ | WITH resource_option_list
+ ;
+
+
+opt_grant_options:
+ /* empty */ {}
+ | WITH grant_option_list {}
+ ;
+
+opt_grant_option:
+ /* empty */ {}
+ | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ ;
+
+grant_option_list:
+ grant_option_list grant_option {}
+ | grant_option {}
+ ;
+
+grant_option:
+ GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ | resource_option {}
+ ;
+
+compound_statement:
+ sp_proc_stmt_compound_ok
+ {
+ Lex->sql_command= SQLCOM_COMPOUND;
+ Lex->sphead->set_stmt_end(thd);
+ Lex->sphead->restore_thd_mem_root(thd);
+ }
+ ;
+
+opt_not:
+ /* nothing */ { $$= 0; }
+ | not { $$= 1; }
+ ;
+
+opt_work:
+ /* empty */ {}
+ | WORK_SYM {}
+ ;
+
+opt_chain:
+ /* empty */
+ { $$= TVL_UNKNOWN; }
+ | AND_SYM NO_SYM CHAIN_SYM { $$= TVL_NO; }
+ | AND_SYM CHAIN_SYM { $$= TVL_YES; }
+ ;
+
+opt_release:
+ /* empty */
+ { $$= TVL_UNKNOWN; }
+ | RELEASE_SYM { $$= TVL_YES; }
+ | NO_SYM RELEASE_SYM { $$= TVL_NO; }
+;
+
+commit:
+ COMMIT_SYM opt_work opt_chain opt_release
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_COMMIT;
+ /* Don't allow AND CHAIN RELEASE. */
+ MYSQL_YYABORT_UNLESS($3 != TVL_YES || $4 != TVL_YES);
+ lex->tx_chain= $3;
+ lex->tx_release= $4;
+ }
+ ;
+
+rollback:
+ ROLLBACK_SYM opt_work opt_chain opt_release
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_ROLLBACK;
+ /* Don't allow AND CHAIN RELEASE. */
+ MYSQL_YYABORT_UNLESS($3 != TVL_YES || $4 != TVL_YES);
+ lex->tx_chain= $3;
+ lex->tx_release= $4;
+ }
+ | ROLLBACK_SYM opt_work TO_SYM SAVEPOINT_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
+ lex->ident= $5;
+ }
+ | ROLLBACK_SYM opt_work TO_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
+ lex->ident= $4;
+ }
+ ;
+
+savepoint:
+ SAVEPOINT_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SAVEPOINT;
+ lex->ident= $2;
+ }
+ ;
+
+release:
+ RELEASE_SYM SAVEPOINT_SYM ident
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_RELEASE_SAVEPOINT;
+ lex->ident= $3;
+ }
+ ;
+
+/*
+ UNIONS : glue selects together
+*/
+
+unit_type_decl:
+ UNION_SYM
+ { $$= UNION_TYPE; }
+ | INTERSECT_SYM
+ { $$= INTERSECT_TYPE; }
+ | EXCEPT_SYM
+ { $$= EXCEPT_TYPE; }
+
+
+union_clause:
+ /* empty */ {}
+ | union_list
+ ;
+
+union_list:
+ unit_type_decl union_option
+ {
+ if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
+ MYSQL_YYABORT;
+ }
+ union_list_part2
+ {
+ /*
+ Remove from the name resolution context stack the context of the
+ last select in the union.
+ */
+ Lex->pop_context();
+ }
+ ;
+
+union_list_view:
+ unit_type_decl union_option
+ {
+ if (Lex->add_select_to_union_list((bool)$2, $1, TRUE))
+ MYSQL_YYABORT;
+ }
+ query_expression_body_view
+ {
+ Lex->pop_context();
+ }
+ ;
+
+union_order_or_limit:
+ {
+ LEX *lex= thd->lex;
+ DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel->master_unit();
+ SELECT_LEX *fake= unit->fake_select_lex;
+ if (fake)
+ {
+ fake->no_table_names_allowed= 1;
+ lex->current_select= fake;
+ }
+ thd->where= "global ORDER clause";
+ }
+ order_or_limit
+ {
+ thd->lex->current_select->no_table_names_allowed= 0;
+ thd->where= "";
+ }
+ ;
+
+order_or_limit:
+ order_clause opt_limit_clause
+ | limit_clause
+ ;
+
+/*
+ Start a UNION, for non-top level query expressions.
+*/
+union_head_non_top:
+ unit_type_decl union_option
+ {
+ if (Lex->add_select_to_union_list((bool)$2, $1, FALSE))
+ MYSQL_YYABORT;
+ }
+ ;
+
+union_option:
+ /* empty */ { $$=1; }
+ | DISTINCT { $$=1; }
+ | ALL { $$=0; }
+ ;
+
+/*
+ Corresponds to the SQL Standard
+ <query specification> ::=
+ SELECT [ <set quantifier> ] <select list> <table expression>
+
+ Notes:
+ - We allow more options in addition to <set quantifier>
+ - <table expression> is optional in MariaDB
+*/
+query_specification:
+ SELECT_SYM select_init2_derived opt_table_expression
+ {
+ $$= Lex->current_select->master_unit()->first_select();
+ }
+ ;
+
+query_term_union_not_ready:
+ query_specification order_or_limit opt_select_lock_type { $$= $1; }
+ | '(' select_paren_derived ')' union_order_or_limit { $$= $2; }
+ ;
+
+query_term_union_ready:
+ query_specification opt_select_lock_type { $$= $1; }
+ | '(' select_paren_derived ')' { $$= $2; }
+ ;
+
+query_expression_body:
+ query_term_union_not_ready { $$= $1; }
+ | query_term_union_ready { $$= $1; }
+ | query_term_union_ready union_list_derived { $$= $1; }
+ ;
+
+/* Corresponds to <query expression> in the SQL:2003 standard. */
+subselect:
+ subselect_start opt_with_clause query_expression_body subselect_end
+ {
+ $3->set_with_clause($2);
+ $$= $3;
+ }
+ ;
+
+subselect_start:
+ {
+ LEX *lex=Lex;
+ if (!lex->expr_allows_subselect ||
+ lex->sql_command == (int)SQLCOM_PURGE)
+ {
+ thd->parse_error();
+ MYSQL_YYABORT;
+ }
+ /*
+ we are making a "derived table" for the parenthesis
+ as we need to have a lex level to fit the union
+ after the parenthesis, e.g.
+ (SELECT .. ) UNION ... becomes
+ SELECT * FROM ((SELECT ...) UNION ...)
+ */
+ if (mysql_new_select(Lex, 1, NULL))
+ MYSQL_YYABORT;
+ }
+ ;
+
+subselect_end:
+ {
+ LEX *lex=Lex;
+
+ lex->check_automatic_up(UNSPECIFIED_TYPE);
+ lex->pop_context();
+ SELECT_LEX *child= lex->current_select;
+ lex->current_select = lex->current_select->return_after_parsing();
+ lex->nest_level--;
+ lex->current_select->n_child_sum_items += child->n_sum_items;
+ /*
+ A subselect can add fields to an outer select. Reserve space for
+ them.
+ */
+ lex->current_select->select_n_where_fields+=
+ child->select_n_where_fields;
+
+ /*
+ Aggregate functions in having clause may add fields to an outer
+ select. Count them also.
+ */
+ lex->current_select->select_n_having_items+=
+ child->select_n_having_items;
+ }
+ ;
+
+opt_query_expression_options:
+ /* empty */
+ | query_expression_option_list
+ ;
+
+query_expression_option_list:
+ query_expression_option_list query_expression_option
+ | query_expression_option
+ ;
+
+query_expression_option:
+ STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
+ | HIGH_PRIORITY
+ {
+ if (check_simple_select())
+ MYSQL_YYABORT;
+ YYPS->m_lock_type= TL_READ_HIGH_PRIORITY;
+ YYPS->m_mdl_type= MDL_SHARED_READ;
+ Select->options|= SELECT_HIGH_PRIORITY;
+ }
+ | DISTINCT { Select->options|= SELECT_DISTINCT; }
+ | UNIQUE_SYM { Select->options|= SELECT_DISTINCT; }
+ | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
+ | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
+ | SQL_BUFFER_RESULT
+ {
+ if (check_simple_select())
+ MYSQL_YYABORT;
+ Select->options|= OPTION_BUFFER_RESULT;
+ }
+ | SQL_CALC_FOUND_ROWS
+ {
+ if (check_simple_select())
+ MYSQL_YYABORT;
+ Select->options|= OPTION_FOUND_ROWS;
+ }
+ | ALL { Select->options|= SELECT_ALL; }
+ ;
+
+/**************************************************************************
+
+ DEFINER clause support.
+
+**************************************************************************/
+
+definer_opt:
+ no_definer
+ | definer
+ ;
+
+no_definer:
+ /* empty */
+ {
+ /*
+ We have to distinguish missing DEFINER-clause from case when
+ CURRENT_USER specified as definer explicitly in order to properly
+ handle CREATE TRIGGER statements which come to replication thread
+ from older master servers (i.e. to create non-suid trigger in this
+ case).
+ */
+ thd->lex->definer= 0;
+ }
+ ;
+
+definer:
+ DEFINER_SYM '=' user_or_role
+ {
+ Lex->definer= $3;
+ Lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
+ Lex->ssl_cipher= Lex->x509_subject= Lex->x509_issuer= 0;
+ bzero(&(Lex->mqh), sizeof(Lex->mqh));
+ }
+ ;
+
+/**************************************************************************
+
+ CREATE VIEW statement parts.
+
+**************************************************************************/
+
+view_algorithm:
+ ALGORITHM_SYM '=' UNDEFINED_SYM { $$= DTYPE_ALGORITHM_UNDEFINED; }
+ | ALGORITHM_SYM '=' MERGE_SYM { $$= VIEW_ALGORITHM_MERGE; }
+ | ALGORITHM_SYM '=' TEMPTABLE_SYM { $$= VIEW_ALGORITHM_TMPTABLE; }
+ ;
+
+opt_view_suid:
+ /* empty */ { $$= VIEW_SUID_DEFAULT; }
+ | view_suid { $$= $1; }
+ ;
+
+view_suid:
+ SQL_SYM SECURITY_SYM DEFINER_SYM { $$= VIEW_SUID_DEFINER; }
+ | SQL_SYM SECURITY_SYM INVOKER_SYM { $$= VIEW_SUID_INVOKER; }
+ ;
+
+view_list_opt:
+ /* empty */
+ {}
+ | '(' view_list ')'
+ ;
+
+view_list:
+ ident
+ {
+ Lex->view_list.push_back((LEX_STRING*)
+ thd->memdup(&$1, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ | view_list ',' ident
+ {
+ Lex->view_list.push_back((LEX_STRING*)
+ thd->memdup(&$3, sizeof(LEX_STRING)),
+ thd->mem_root);
+ }
+ ;
+
+view_select:
+ {
+ LEX *lex= Lex;
+ lex->parsing_options.allows_variable= FALSE;
+ lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr();
+ }
+ opt_with_clause query_expression_body_view view_check_option
+ {
+ LEX *lex= Lex;
+ uint len= YYLIP->get_cpp_ptr() - lex->create_view->select.str;
+ uint not_used;
+ void *create_view_select= thd->memdup(lex->create_view->select.str, len);
+ lex->create_view->select.length= len;
+ lex->create_view->select.str= (char *) create_view_select;
+ trim_whitespace(thd->charset(),
+ &lex->create_view->select,
+ &not_used);
+ lex->create_view->check= $4;
+ lex->parsing_options.allows_variable= TRUE;
+ lex->current_select->set_with_clause($2);
+ }
+ ;
+
+/*
+ SQL Standard <query expression body> for VIEWs.
+ Does not include INTO and PROCEDURE clauses.
+*/
+query_expression_body_view:
+ SELECT_SYM select_options_and_item_list select_init3_view
+ | '(' select_paren_view ')'
+ | '(' select_paren_view ')' union_order_or_limit
+ | '(' select_paren_view ')' union_list_view
+ ;
+
+view_check_option:
+ /* empty */ { $$= VIEW_CHECK_NONE; }
+ | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
+ | WITH CASCADED CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; }
+ | WITH LOCAL_SYM CHECK_SYM OPTION { $$= VIEW_CHECK_LOCAL; }
+ ;
+
+/**************************************************************************
+
+ CREATE TRIGGER statement parts.
+
+**************************************************************************/
+
+trigger_action_order:
+ FOLLOWS_SYM
+ { $$= TRG_ORDER_FOLLOWS; }
+ | PRECEDES_SYM
+ { $$= TRG_ORDER_PRECEDES; }
+ ;
+
+trigger_follows_precedes_clause:
+ /* empty */
+ {
+ $$.ordering_clause= TRG_ORDER_NONE;
+ $$.anchor_trigger_name.str= NULL;
+ $$.anchor_trigger_name.length= 0;
+ }
+ |
+ trigger_action_order ident_or_text
+ {
+ $$.ordering_clause= $1;
+ $$.anchor_trigger_name= $2;
+ }
+ ;
+
+trigger_tail:
+ remember_name
+ opt_if_not_exists
+ {
+ if (Lex->add_create_options_with_check($2))
+ MYSQL_YYABORT;
+ }
+ sp_name
+ trg_action_time
+ trg_event
+ ON
+ remember_name /* $8 */
+ { /* $9 */
+ Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start();
+ }
+ table_ident /* $10 */
+ FOR_SYM
+ remember_name /* $12 */
+ { /* $13 */
+ Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start();
+ }
+ EACH_SYM
+ ROW_SYM
+ {
+ Lex->trg_chistics.ordering_clause_begin= YYLIP->get_cpp_ptr();
+ }
+ trigger_follows_precedes_clause /* $17 */
+ { /* $18 */
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= YYLIP;
+
+ if (lex->sphead)
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"));
+
+ lex->stmt_definition_begin= $1;
+ lex->ident.str= $8;
+ lex->ident.length= $12 - $8;
+ lex->spname= $4;
+ (*static_cast<st_trg_execution_order*>(&lex->trg_chistics))= ($17);
+ lex->trg_chistics.ordering_clause_end= lip->get_cpp_ptr();
+
+ if (!lex->make_sp_head(thd, $4, TYPE_ENUM_TRIGGER))
+ MYSQL_YYABORT;
+
+ lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
+ }
+ sp_proc_stmt /* $19 */
+ { /* $20 */
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ if (sp->check_unresolved_goto())
+ MYSQL_YYABORT;
+
+ lex->sql_command= SQLCOM_CREATE_TRIGGER;
+ sp->set_stmt_end(thd);
+ sp->restore_thd_mem_root(thd);
+
+ if (sp->is_not_allowed_in_function("trigger"))
+ MYSQL_YYABORT;
+
+ /*
+ We have to do it after parsing trigger body, because some of
+ sp_proc_stmt alternatives are not saving/restoring LEX, so
+ lex->query_tables can be wiped out.
+ */
+ if (!lex->select_lex.add_table_to_list(thd, $10,
+ (LEX_CSTRING*) 0,
+ TL_OPTION_UPDATING,
+ TL_READ_NO_INSERT,
+ MDL_SHARED_NO_WRITE))
+ MYSQL_YYABORT;
+ }
+ ;
+
+/**************************************************************************
+
+ CREATE FUNCTION | PROCEDURE statements parts.
+
+**************************************************************************/
+
+udf_tail:
+ opt_if_not_exists ident
+ RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
+ {
+ LEX *lex= thd->lex;
+ if (lex->add_create_options_with_check($1))
+ MYSQL_YYABORT;
+ if (is_native_function(thd, & $2))
+ my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $2.str));
+ lex->sql_command= SQLCOM_CREATE_FUNCTION;
+ lex->udf.name= $2;
+ lex->udf.returns= (Item_result) $4;
+ lex->udf.dl= $6.str;
+ }
+ ;
+
+
+sf_return_type:
+ RETURN_SYM
+ {
+ LEX *lex= Lex;
+ lex->init_last_field(&lex->sphead->m_return_field_def,
+ &empty_clex_str,
+ thd->variables.collation_database);
+ }
+ sp_param_type_with_opt_collate
+ {
+ if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
+ MYSQL_YYABORT;
+ }
+ ;
+
+sf_tail:
+ opt_if_not_exists
+ sp_name
+ {
+ if (!Lex->make_sp_head_no_recursive(thd, $1, $2,
+ TYPE_ENUM_FUNCTION))
+ MYSQL_YYABORT;
+ }
+ opt_sp_parenthesized_fdparam_list
+ sf_return_type
+ sp_c_chistics
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= YYLIP;
+
+ lex->sphead->set_chistics(lex->sp_chistics);
+ lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
+ }
+ sp_tail_is
+ sp_body
+ {
+ LEX *lex= thd->lex;
+ sp_head *sp= lex->sphead;
+ if (sp->check_unresolved_goto())
+ MYSQL_YYABORT;
+
+ if (sp->is_not_allowed_in_function("function"))
+ MYSQL_YYABORT;
+
+ lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
+ sp->set_stmt_end(thd);
+ if (!(sp->m_flags & sp_head::HAS_RETURN))
+ my_yyabort_error((ER_SP_NORETURN, MYF(0),
+ ErrConvDQName(sp).ptr()));
+ (void) is_native_function_with_warn(thd, &sp->m_name);
+ sp->restore_thd_mem_root(thd);
+ }
+ ;
+
+sp_tail:
+ opt_if_not_exists sp_name
+ {
+ if (!Lex->make_sp_head_no_recursive(thd, $1, $2,
+ TYPE_ENUM_PROCEDURE))
+ MYSQL_YYABORT;
+ }
+ opt_sp_parenthesized_pdparam_list
+ sp_c_chistics
+ {
+ Lex->sphead->set_chistics(Lex->sp_chistics);
+ Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
+ }
+ sp_tail_is
+ sp_body
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ if (sp->check_unresolved_goto())
+ MYSQL_YYABORT;
+ sp->set_stmt_end(thd);
+ lex->sql_command= SQLCOM_CREATE_PROCEDURE;
+ sp->restore_thd_mem_root(thd);
+ }
+ ;
+
+sf_tail_standalone:
+ sf_tail opt_sp_name
+ {
+ if ($2 && !$2->eq(Lex->sphead))
+ my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0),
+ ErrConvDQName($2).ptr(),
+ ErrConvDQName(Lex->sphead).ptr()));
+ }
+ ;
+
+sp_tail_standalone:
+ sp_tail opt_sp_name
+ {
+ if ($2 && !$2->eq(Lex->sphead))
+ my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0),
+ ErrConvDQName($2).ptr(),
+ ErrConvDQName(Lex->sphead).ptr()));
+ }
+ ;
+
+sp_tail_is:
+ IS
+ | AS
+ ;
+
+/*************************************************************************/
+
+xa:
+ XA_SYM begin_or_start xid opt_join_or_resume
+ {
+ Lex->sql_command = SQLCOM_XA_START;
+ }
+ | XA_SYM END xid opt_suspend
+ {
+ Lex->sql_command = SQLCOM_XA_END;
+ }
+ | XA_SYM PREPARE_SYM xid
+ {
+ Lex->sql_command = SQLCOM_XA_PREPARE;
+ }
+ | XA_SYM COMMIT_SYM xid opt_one_phase
+ {
+ Lex->sql_command = SQLCOM_XA_COMMIT;
+ }
+ | XA_SYM ROLLBACK_SYM xid
+ {
+ Lex->sql_command = SQLCOM_XA_ROLLBACK;
+ }
+ | XA_SYM RECOVER_SYM
+ {
+ Lex->sql_command = SQLCOM_XA_RECOVER;
+ }
+ ;
+
+xid:
+ text_string
+ {
+ MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE);
+ if (!(Lex->xid=(XID *)thd->alloc(sizeof(XID))))
+ MYSQL_YYABORT;
+ Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
+ }
+ | text_string ',' text_string
+ {
+ MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ if (!(Lex->xid=(XID *)thd->alloc(sizeof(XID))))
+ MYSQL_YYABORT;
+ Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
+ }
+ | text_string ',' text_string ',' ulong_num
+ {
+ MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
+ if (!(Lex->xid=(XID *)thd->alloc(sizeof(XID))))
+ MYSQL_YYABORT;
+ Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
+ }
+ ;
+
+begin_or_start:
+ BEGIN_SYM {}
+ | START_SYM {}
+ ;
+
+opt_join_or_resume:
+ /* nothing */ { Lex->xa_opt=XA_NONE; }
+ | JOIN_SYM { Lex->xa_opt=XA_JOIN; }
+ | RESUME_SYM { Lex->xa_opt=XA_RESUME; }
+ ;
+
+opt_one_phase:
+ /* nothing */ { Lex->xa_opt=XA_NONE; }
+ | ONE_SYM PHASE_SYM { Lex->xa_opt=XA_ONE_PHASE; }
+ ;
+
+opt_suspend:
+ /* nothing */
+ { Lex->xa_opt=XA_NONE; }
+ | SUSPEND_SYM
+ { Lex->xa_opt=XA_SUSPEND; }
+ opt_migrate
+ ;
+
+opt_migrate:
+ /* nothing */ {}
+ | FOR_SYM MIGRATE_SYM { Lex->xa_opt=XA_FOR_MIGRATE; }
+ ;
+
+install:
+ INSTALL_SYM PLUGIN_SYM ident SONAME_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_INSTALL_PLUGIN;
+ lex->comment= $3;
+ lex->ident= $5;
+ }
+ | INSTALL_SYM SONAME_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_INSTALL_PLUGIN;
+ lex->comment= null_clex_str;
+ lex->ident= $3;
+ }
+ ;
+
+uninstall:
+ UNINSTALL_SYM PLUGIN_SYM ident
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
+ lex->comment= $3;
+ }
+ | UNINSTALL_SYM SONAME_SYM TEXT_STRING_sys
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
+ lex->comment= null_clex_str;
+ lex->ident= $3;
+ }
+ ;
+
+/* Avoid compiler warning from sql_yacc.cc where yyerrlab1 is not used */
+keep_gcc_happy:
+ IMPOSSIBLE_ACTION
+ {
+ YYERROR;
+ }
+
+/**
+ @} (end of group Parser)
+*/
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index bf5fe9d6f00..01c9fe4e70b 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -331,10 +331,10 @@ outp:
>=0 Ordinal position
*/
-int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
+int find_string_in_array(LEX_CSTRING * const haystack, LEX_CSTRING * const needle,
CHARSET_INFO * const cs)
{
- const LEX_STRING *pos;
+ const LEX_CSTRING *pos;
for (pos= haystack; pos->str; pos++)
if (!cs->coll->strnncollsp(cs, (uchar *) pos->str, pos->length,
(uchar *) needle->str, needle->length))
@@ -345,12 +345,12 @@ int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
}
-char *set_to_string(THD *thd, LEX_STRING *result, ulonglong set,
- const char *lib[])
+const char *set_to_string(THD *thd, LEX_CSTRING *result, ulonglong set,
+ const char *lib[])
{
char buff[STRING_BUFFER_USUAL_SIZE*8];
String tmp(buff, sizeof(buff), &my_charset_latin1);
- LEX_STRING unused;
+ LEX_CSTRING unused;
if (!result)
result= &unused;
@@ -376,12 +376,12 @@ char *set_to_string(THD *thd, LEX_STRING *result, ulonglong set,
return result->str;
}
-char *flagset_to_string(THD *thd, LEX_STRING *result, ulonglong set,
- const char *lib[])
+const char *flagset_to_string(THD *thd, LEX_CSTRING *result, ulonglong set,
+ const char *lib[])
{
char buff[STRING_BUFFER_USUAL_SIZE*8];
String tmp(buff, sizeof(buff), &my_charset_latin1);
- LEX_STRING unused;
+ LEX_CSTRING unused;
if (!result) result= &unused;
diff --git a/sql/strfunc.h b/sql/strfunc.h
index 7b031710c76..7f3021e1a6d 100644
--- a/sql/strfunc.h
+++ b/sql/strfunc.h
@@ -33,12 +33,13 @@ uint find_type2(const TYPELIB *lib, const char *find, uint length,
void unhex_type2(TYPELIB *lib);
uint check_word(TYPELIB *lib, const char *val, const char *end,
const char **end_of_word);
-int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
+int find_string_in_array(LEX_CSTRING * const haystack,
+ LEX_CSTRING * const needle,
CHARSET_INFO * const cs);
-char *flagset_to_string(THD *thd, LEX_STRING *result, ulonglong set,
+const char *flagset_to_string(THD *thd, LEX_CSTRING *result, ulonglong set,
const char *lib[]);
-char *set_to_string(THD *thd, LEX_STRING *result, ulonglong set,
- const char *lib[]);
+const char *set_to_string(THD *thd, LEX_CSTRING *result, ulonglong set,
+ const char *lib[]);
/*
These functions were protected by INNODB_COMPATIBILITY_HOOKS
diff --git a/sql/structs.h b/sql/structs.h
index 98eb0f2585d..982eda99d30 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -29,6 +29,7 @@
#include <mysql_com.h> /* USERNAME_LENGTH */
struct TABLE;
+class Type_handler;
class Field;
class Index_statistics;
@@ -124,10 +125,10 @@ typedef struct st_key {
union
{
plugin_ref parser; /* Fulltext [pre]parser */
- LEX_STRING *parser_name; /* Fulltext [pre]parser name */
+ LEX_CSTRING *parser_name; /* Fulltext [pre]parser name */
};
KEY_PART_INFO *key_part;
- char *name; /* Name of key */
+ const char *name; /* Name of key */
/* Unique name for cache; db + \0 + table_name + \0 + key_name + \0 */
uchar *cache_name;
/*
@@ -152,7 +153,7 @@ typedef struct st_key {
int bdb_return_if_eq;
} handler;
TABLE *table;
- LEX_STRING comment;
+ LEX_CSTRING comment;
/** reference to the list of options or NULL */
engine_option_value *option_list;
ha_index_option_struct *option_struct; /* structure with parsed options */
@@ -203,24 +204,37 @@ extern const char *show_comp_option_name[];
typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
-typedef struct st_lex_user {
- LEX_STRING user, host, plugin, auth;
- LEX_STRING pwtext, pwhash;
+
+struct AUTHID
+{
+ LEX_CSTRING user, host;
+ void init() { memset(this, 0, sizeof(*this)); }
+ void copy(MEM_ROOT *root, const LEX_CSTRING *usr, const LEX_CSTRING *host);
bool is_role() const { return user.str[0] && !host.str[0]; }
- void set_lex_string(LEX_STRING *l, char *buf)
+ void set_lex_string(LEX_CSTRING *l, char *buf)
{
if (is_role())
*l= user;
else
- l->length= strxmov(l->str= buf, user.str, "@", host.str, NullS) - buf;
+ {
+ l->str= buf;
+ l->length= strxmov(buf, user.str, "@", host.str, NullS) - buf;
+ }
}
+};
+
+
+struct LEX_USER: public AUTHID
+{
+ LEX_CSTRING plugin, auth;
+ LEX_CSTRING pwtext, pwhash;
void reset_auth()
{
pwtext.length= pwhash.length= plugin.length= auth.length= 0;
pwtext.str= pwhash.str= 0;
- plugin.str= auth.str= const_cast<char*>("");
+ plugin.str= auth.str= "";
}
-} LEX_USER;
+};
/*
This structure specifies the maximum amount of resources which
@@ -578,27 +592,27 @@ public:
struct Lex_field_type_st: public Lex_length_and_dec_st
{
private:
- enum_field_types m_type;
- void set(enum_field_types type, const char *length, const char *dec)
+ const Type_handler *m_handler;
+ void set(const Type_handler *handler, const char *length, const char *dec)
{
- m_type= type;
+ m_handler= handler;
Lex_length_and_dec_st::set(length, dec);
}
public:
- void set(enum_field_types type, Lex_length_and_dec_st length_and_dec)
+ void set(const Type_handler *handler, Lex_length_and_dec_st length_and_dec)
{
- m_type= type;
+ m_handler= handler;
Lex_length_and_dec_st::operator=(length_and_dec);
}
- void set(enum_field_types type, const char *length)
+ void set(const Type_handler *handler, const char *length)
{
- set(type, length, 0);
+ set(handler, length, 0);
}
- void set(enum_field_types type)
+ void set(const Type_handler *handler)
{
- set(type, 0, 0);
+ set(handler, 0, 0);
}
- enum_field_types field_type() const { return m_type; }
+ const Type_handler *type_handler() const { return m_handler; }
};
@@ -629,4 +643,89 @@ public:
};
+struct Lex_spblock_handlers_st
+{
+public:
+ int hndlrs;
+ void init(int count) { hndlrs= count; }
+};
+
+
+struct Lex_spblock_st: public Lex_spblock_handlers_st
+{
+public:
+ int vars;
+ int conds;
+ int curs;
+ void init()
+ {
+ vars= conds= hndlrs= curs= 0;
+ }
+ void init_using_vars(uint nvars)
+ {
+ vars= nvars;
+ conds= hndlrs= curs= 0;
+ }
+ void join(const Lex_spblock_st &b1, const Lex_spblock_st &b2)
+ {
+ vars= b1.vars + b2.vars;
+ conds= b1.conds + b2.conds;
+ hndlrs= b1.hndlrs + b2.hndlrs;
+ curs= b1.curs + b2.curs;
+ }
+};
+
+
+class Lex_spblock: public Lex_spblock_st
+{
+public:
+ Lex_spblock() { init(); }
+ Lex_spblock(const Lex_spblock_handlers_st &other)
+ {
+ vars= conds= curs= 0;
+ hndlrs= other.hndlrs;
+ }
+};
+
+
+struct Lex_for_loop_bounds_st
+{
+public:
+ class sp_assignment_lex *m_index;
+ class sp_assignment_lex *m_upper_bound;
+ int8 m_direction;
+ bool m_implicit_cursor;
+ bool is_for_loop_cursor() const { return m_upper_bound == NULL; }
+};
+
+
+struct Lex_for_loop_st
+{
+public:
+ class sp_variable *m_index;
+ class sp_variable *m_upper_bound;
+ int m_cursor_offset;
+ int8 m_direction;
+ bool m_implicit_cursor;
+ void init()
+ {
+ m_index= 0;
+ m_upper_bound= 0;
+ m_direction= 0;
+ m_implicit_cursor= false;
+ }
+ void init(const Lex_for_loop_st &other)
+ {
+ *this= other;
+ }
+ bool is_for_loop_cursor() const { return m_upper_bound == NULL; }
+};
+
+
+struct Lex_string_with_pos_st: public LEX_CSTRING
+{
+ const char *m_pos;
+};
+
+
#endif /* STRUCTS_INCLUDED */
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index e2071184365..ebf5ea22024 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1026,7 +1026,7 @@ static Sys_var_lexstring Sys_init_connect(
#ifdef HAVE_REPLICATION
static bool check_master_connection(sys_var *self, THD *thd, set_var *var)
{
- LEX_STRING tmp;
+ LEX_CSTRING tmp;
tmp.str= var->save_result.string_value.str;
tmp.length= var->save_result.string_value.length;
if (!tmp.str || check_master_connection_name(&tmp))
@@ -1558,7 +1558,7 @@ static Sys_var_gtid_binlog_pos Sys_gtid_binlog_pos(
uchar *
-Sys_var_gtid_binlog_pos::global_value_ptr(THD *thd, const LEX_STRING *base)
+Sys_var_gtid_binlog_pos::global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
char buf[128];
String str(buf, sizeof(buf), system_charset_info);
@@ -1586,7 +1586,7 @@ static Sys_var_gtid_current_pos Sys_gtid_current_pos(
uchar *
-Sys_var_gtid_current_pos::global_value_ptr(THD *thd, const LEX_STRING *base)
+Sys_var_gtid_current_pos::global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
String str;
char *p;
@@ -1667,7 +1667,7 @@ Sys_var_gtid_slave_pos::global_update(THD *thd, set_var *var)
uchar *
-Sys_var_gtid_slave_pos::global_value_ptr(THD *thd, const LEX_STRING *base)
+Sys_var_gtid_slave_pos::global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
String str;
char *p;
@@ -1788,7 +1788,7 @@ Sys_var_gtid_binlog_state::global_update(THD *thd, set_var *var)
uchar *
-Sys_var_gtid_binlog_state::global_value_ptr(THD *thd, const LEX_STRING *base)
+Sys_var_gtid_binlog_state::global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
char buf[512];
String str(buf, sizeof(buf), system_charset_info);
@@ -1821,7 +1821,7 @@ static Sys_var_last_gtid Sys_last_gtid(
uchar *
-Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_STRING *base)
+Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
char buf[10+1+10+1+20+1];
String str(buf, sizeof(buf), system_charset_info);
@@ -1930,7 +1930,7 @@ Sys_var_slave_parallel_mode::global_update(THD *thd, set_var *var)
{
enum_slave_parallel_mode new_value=
(enum_slave_parallel_mode)var->save_result.ulonglong_value;
- LEX_STRING *base_name= &var->base;
+ LEX_CSTRING *base_name= &var->base;
Master_info *mi;
bool res= false;
@@ -1950,7 +1950,7 @@ Sys_var_slave_parallel_mode::global_update(THD *thd, set_var *var)
if (mi->rli.slave_running)
{
my_error(ER_SLAVE_MUST_STOP, MYF(0),
- mi->connection_name.length, mi->connection_name.str);
+ (int) mi->connection_name.length, mi->connection_name.str);
res= true;
}
else
@@ -1973,7 +1973,7 @@ Sys_var_slave_parallel_mode::global_update(THD *thd, set_var *var)
uchar *
Sys_var_slave_parallel_mode::global_value_ptr(THD *thd,
- const LEX_STRING *base_name)
+ const LEX_CSTRING *base_name)
{
Master_info *mi;
enum_slave_parallel_mode val=
@@ -3079,7 +3079,7 @@ static const char *sql_mode_names[]=
};
export bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
- LEX_STRING *ls)
+ LEX_CSTRING *ls)
{
set_to_string(thd, ls, sql_mode, sql_mode_names);
return ls->str == 0;
@@ -4372,7 +4372,7 @@ static Sys_var_mybool Sys_relay_log_recovery(
bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var)
{
bool result= true; // Assume error
- LEX_STRING *base_name= &var->base;
+ LEX_CSTRING *base_name= &var->base;
if (!base_name->length)
base_name= &thd->variables.default_master_connection;
@@ -4386,7 +4386,7 @@ bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var)
if (mi->rli.slave_running)
{
my_error(ER_SLAVE_MUST_STOP, MYF(0),
- mi->connection_name.length,
+ (int) mi->connection_name.length,
mi->connection_name.str);
result= true;
}
@@ -4433,7 +4433,7 @@ bool Sys_var_rpl_filter::set_filter_value(const char *value, Master_info *mi)
}
uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd,
- const LEX_STRING *base_name)
+ const LEX_CSTRING *base_name)
{
char buf[256];
String tmp(buf, sizeof(buf), &my_charset_bin);
@@ -4589,7 +4589,7 @@ static bool update_slave_skip_counter(sys_var *self, THD *thd, Master_info *mi)
{
if (mi->rli.slave_running)
{
- my_error(ER_SLAVE_MUST_STOP, MYF(0), mi->connection_name.length,
+ my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length,
mi->connection_name.str);
return true;
}
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index 780450b484b..f9acfb3b657 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -364,9 +364,9 @@ public:
{ var->save_result.ulonglong_value= option.def_value; }
uchar *valptr(THD *thd, ulong val)
{ return (uchar*)typelib.type_names[val]; }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, session_var(thd, ulong)); }
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(ulong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, option.def_value); }
@@ -612,14 +612,16 @@ public:
/* parse and feel list with default values */
if (thd)
{
+#ifndef DBUG_OFF
bool res=
+#endif
sysvartrack_validate_value(thd,
var->save_result.string_value.str,
var->save_result.string_value.length);
DBUG_ASSERT(res == 0);
}
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(thd != NULL);
size_t len= sysvartrack_value_len(thd);
@@ -669,7 +671,7 @@ public:
void global_save_default(THD *thd, set_var *var)
{ DBUG_ASSERT(FALSE); }
protected:
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return thd->security_ctx->proxy_user[0] ?
(uchar *) &(thd->security_ctx->proxy_user[0]) : NULL;
@@ -685,7 +687,7 @@ public:
{}
protected:
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return (uchar*)thd->security_ctx->external_user;
}
@@ -725,7 +727,7 @@ public:
bool global_update(THD *thd, set_var *var);
protected:
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
bool set_filter_value(const char *value, Master_info *mi);
};
@@ -736,7 +738,7 @@ protected:
Class specific constructor arguments:
enum charset_enum is_os_charset_arg
- Backing store: LEX_STRING
+ Backing store: LEX_CSTRING
@note
Behaves exactly as Sys_var_charptr, only the backing store is different.
@@ -757,22 +759,22 @@ public:
getopt, is_os_charset_arg, def_val, lock, binlog_status_arg,
on_check_func, on_update_func, substitute)
{
- global_var(LEX_STRING).length= strlen(def_val);
- SYSVAR_ASSERT(size == sizeof(LEX_STRING));
+ global_var(LEX_CSTRING).length= strlen(def_val);
+ SYSVAR_ASSERT(size == sizeof(LEX_CSTRING));
*const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
}
bool global_update(THD *thd, set_var *var)
{
if (Sys_var_charptr::global_update(thd, var))
return true;
- global_var(LEX_STRING).length= var->save_result.string_value.length;
+ global_var(LEX_CSTRING).length= var->save_result.string_value.length;
return false;
}
};
/*
- A LEX_STRING stored only in thd->variables
+ A LEX_CSTRING stored only in thd->variables
Only to be used for small buffers
*/
@@ -822,10 +824,10 @@ public:
}
bool session_update(THD *thd, set_var *var)
{
- LEX_STRING *tmp= &session_var(thd, LEX_STRING);
+ LEX_CSTRING *tmp= &session_var(thd, LEX_CSTRING);
tmp->length= var->save_result.string_value.length;
/* Store as \0 terminated string (just to be safe) */
- strmake(tmp->str, var->save_result.string_value.str, tmp->length);
+ strmake((char*) tmp->str, var->save_result.string_value.str, tmp->length);
return false;
}
bool global_update(THD *thd, set_var *var)
@@ -843,7 +845,7 @@ public:
{
DBUG_ASSERT(FALSE);
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(FALSE);
return NULL;
@@ -913,13 +915,13 @@ public:
char *ptr= (char*)(intptr)option.def_value;
var->save_result.string_value.str= ptr;
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
char buf[256];
DBUG_EXPLAIN(buf, sizeof(buf));
return (uchar*) thd->strdup(buf);
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
char buf[256];
DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
@@ -974,7 +976,7 @@ public:
bool global_update(THD *thd, set_var *var)
{
ulonglong new_value= var->save_result.ulonglong_value;
- LEX_STRING *base_name= &var->base;
+ LEX_CSTRING *base_name= &var->base;
KEY_CACHE *key_cache;
/* If no basename, assume it's for the key cache named 'default' */
@@ -1001,7 +1003,7 @@ public:
return keycache_update(thd, key_cache, offset, new_value);
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
KEY_CACHE *key_cache= get_key_cache(base);
if (!key_cache)
@@ -1186,7 +1188,7 @@ public:
lock, binlog_status_arg, on_check_func, on_update_func,
substitute)
{ }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
if (thd->user_connect && thd->user_connect->user_resources.user_conn)
return (uchar*) &(thd->user_connect->user_resources.user_conn);
@@ -1300,9 +1302,9 @@ public:
{ var->save_result.ulonglong_value= option.def_value; }
uchar *valptr(THD *thd, ulonglong val)
{ return (uchar*)flagset_to_string(thd, 0, val, typelib.type_names); }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, session_var(thd, ulonglong)); }
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(ulonglong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, option.def_value); }
@@ -1399,9 +1401,9 @@ public:
{ var->save_result.ulonglong_value= option.def_value; }
uchar *valptr(THD *thd, ulonglong val)
{ return (uchar*)set_to_string(thd, 0, val, typelib.type_names); }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, session_var(thd, ulonglong)); }
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(ulonglong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, option.def_value); }
@@ -1450,7 +1452,7 @@ public:
var->save_result.plugin= NULL;
else
{
- const LEX_STRING pname= { const_cast<char*>(res->ptr()), res->length() };
+ const LEX_CSTRING pname= { const_cast<char*>(res->ptr()), res->length() };
plugin_ref plugin;
// special code for storage engines (e.g. to handle historical aliases)
@@ -1504,7 +1506,7 @@ public:
if (!default_value)
return 0;
- LEX_STRING pname= { default_value, strlen(pname.str) };
+ LEX_CSTRING pname= { default_value, strlen(default_value) };
plugin_ref plugin;
if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
@@ -1525,9 +1527,9 @@ public:
return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str,
plugin_name(plugin)->length) : 0);
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, session_var(thd, plugin_ref)); }
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(plugin_ref)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, get_default(thd)); }
@@ -1593,11 +1595,11 @@ public:
{
DBUG_ASSERT(FALSE);
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return debug_sync_value_ptr(thd);
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(FALSE);
return 0;
@@ -1680,9 +1682,9 @@ public:
thd->sys_var_tmp.my_bool_value= reverse_semantics ^ ((val & bitmask) != 0);
return (uchar*) &thd->sys_var_tmp.my_bool_value;
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, session_var(thd, ulonglong)); }
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(ulonglong)); }
uchar *default_value_ptr(THD *thd)
{
@@ -1743,12 +1745,12 @@ public:
{ var->value= 0; }
void global_save_default(THD *thd, set_var *var)
{ DBUG_ASSERT(FALSE); }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
thd->sys_var_tmp.ulonglong_value= read_func(thd);
return (uchar*) &thd->sys_var_tmp.ulonglong_value;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(FALSE);
return 0;
@@ -1808,13 +1810,13 @@ public:
{ var->value= 0; }
void global_save_default(THD *thd, set_var *var)
{ DBUG_ASSERT(FALSE); }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
thd->sys_var_tmp.double_value= thd->start_time +
thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR;
return (uchar*) &thd->sys_var_tmp.double_value;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(FALSE);
return 0;
@@ -1878,12 +1880,12 @@ public:
}
void session_save_default(THD *thd, set_var *var) { }
void global_save_default(THD *thd, set_var *var) { }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(FALSE);
return 0;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)];
}
@@ -1955,9 +1957,9 @@ public:
}
uchar *valptr(THD *thd, uchar *val)
{ return val ? *(uchar**)(val+name_offset) : 0; }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, session_var(thd, uchar*)); }
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(uchar*)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, *(uchar**)option.def_value); }
@@ -2031,7 +2033,7 @@ public:
}
uchar *valptr(THD *thd, Time_zone *val)
{ return (uchar *)(val->get_name()->ptr()); }
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
/*
This is an ugly fix for replication: we don't replicate properly queries
@@ -2044,7 +2046,7 @@ public:
thd->time_zone_used= 1;
return valptr(thd, session_var(thd, Time_zone *));
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{ return valptr(thd, global_var(Time_zone*)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, *(Time_zone**)option.def_value); }
@@ -2215,7 +2217,7 @@ public:
/* Use value given in variable declaration */
global_save_default(thd, var);
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
ulonglong *tmp, res;
tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset);
@@ -2223,7 +2225,7 @@ public:
*tmp= res;
return (uchar*) tmp;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
return session_value_ptr(thd, base);
}
@@ -2275,12 +2277,12 @@ public:
{
DBUG_ASSERT(false);
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(false);
return NULL;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
};
@@ -2324,12 +2326,12 @@ public:
{
DBUG_ASSERT(false);
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(false);
return NULL;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
};
@@ -2364,12 +2366,12 @@ public:
/* Record the attempt to use default so we can error. */
var->value= 0;
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(false);
return NULL;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
uchar *default_value_ptr(THD *thd)
{ return 0; }
};
@@ -2406,12 +2408,12 @@ public:
/* Record the attempt to use default so we can error. */
var->value= 0;
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(false);
return NULL;
}
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
uchar *default_value_ptr(THD *thd)
{ return 0; }
};
@@ -2456,8 +2458,8 @@ public:
{
DBUG_ASSERT(false);
}
- uchar *session_value_ptr(THD *thd, const LEX_STRING *base);
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base)
+ uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
{
DBUG_ASSERT(false);
return NULL;
@@ -2483,5 +2485,5 @@ public:
SYSVAR_ASSERT(scope() == GLOBAL);
}
bool global_update(THD *thd, set_var *var);
- uchar *global_value_ptr(THD *thd, const LEX_STRING *base);
+ uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
};
diff --git a/sql/table.cc b/sql/table.cc
index b03f64bc7e0..7432277f448 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -42,6 +42,7 @@
#include "sql_view.h"
#include "rpl_filter.h"
#include "sql_cte.h"
+#include "ha_sequence.h"
/* For MySQL 5.7 virtual fields */
#define MYSQL57_GENERATED_FIELD 128
@@ -52,25 +53,25 @@ static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *,
static bool check_vcol_forward_refs(Field *, Virtual_column_info *);
/* INFORMATION_SCHEMA name */
-LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")};
+LEX_CSTRING INFORMATION_SCHEMA_NAME= {STRING_WITH_LEN("information_schema")};
/* PERFORMANCE_SCHEMA name */
-LEX_STRING PERFORMANCE_SCHEMA_DB_NAME= {C_STRING_WITH_LEN("performance_schema")};
+LEX_CSTRING PERFORMANCE_SCHEMA_DB_NAME= {STRING_WITH_LEN("performance_schema")};
/* MYSQL_SCHEMA name */
-LEX_STRING MYSQL_SCHEMA_NAME= {C_STRING_WITH_LEN("mysql")};
+LEX_CSTRING MYSQL_SCHEMA_NAME= {STRING_WITH_LEN("mysql")};
/* GENERAL_LOG name */
-LEX_STRING GENERAL_LOG_NAME= {C_STRING_WITH_LEN("general_log")};
+LEX_CSTRING GENERAL_LOG_NAME= {STRING_WITH_LEN("general_log")};
/* SLOW_LOG name */
-LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")};
+LEX_CSTRING SLOW_LOG_NAME= {STRING_WITH_LEN("slow_log")};
/*
Keyword added as a prefix when parsing the defining expression for a
virtual column read from the column definition saved in the frm file
*/
-static LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
+static LEX_CSTRING parse_vcol_keyword= { STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
static int64 last_table_id;
@@ -207,8 +208,8 @@ View_creation_ctx * View_creation_ctx::create(THD *thd,
static uchar *get_field_name(Field **buff, size_t *length,
my_bool not_used __attribute__((unused)))
{
- *length= (uint) strlen((*buff)->field_name);
- return (uchar*) (*buff)->field_name;
+ *length= (uint) (*buff)->field_name.length;
+ return (uchar*) (*buff)->field_name.str;
}
@@ -241,7 +242,8 @@ char *fn_rext(char *name)
return name + strlen(name);
}
-TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name)
+TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
+ const LEX_CSTRING *name)
{
DBUG_ASSERT(db != NULL);
DBUG_ASSERT(name != NULL);
@@ -321,7 +323,7 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
share->path.str= path_buff;
share->path.length= path_length;
- strmov(share->path.str, path);
+ strmov(path_buff, path);
share->normalized_path.str= share->path.str;
share->normalized_path.length= path_length;
share->table_category= get_table_category(& share->db, & share->table_name);
@@ -431,6 +433,7 @@ void TABLE_SHARE::destroy()
ha_share= NULL; // Safety
}
+ delete sequence;
free_root(&stats_cb.mem_root, MYF(0));
stats_cb.stats_can_be_read= FALSE;
stats_cb.stats_is_read= FALSE;
@@ -619,7 +622,7 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
share->is_view= 1;
if (flags & GTS_VIEW)
{
- LEX_STRING pathstr= { path, length };
+ LEX_CSTRING pathstr= { path, length };
/*
Create view file parser and hold it in TABLE_SHARE member
view_def.
@@ -1174,7 +1177,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
char *keynames, *names, *comment_pos;
const uchar *forminfo, *extra2;
const uchar *frm_image_end = frm_image + frm_length;
- uchar *record, *null_flags, *null_pos, *mysql57_vcol_null_pos;
+ uchar *record, *null_flags, *null_pos, *mysql57_vcol_null_pos= 0;
const uchar *disk_buff, *strpos;
ulong pos, record_offset;
ulong rec_buff_length;
@@ -1271,7 +1274,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
case EXTRA2_DEFAULT_PART_ENGINE:
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
- LEX_STRING name= { (char*)extra2, length };
+ LEX_CSTRING name= { (char*)extra2, length };
share->default_part_plugin= ha_resolve_by_name(NULL, &name, false);
if (!share->default_part_plugin)
goto err;
@@ -1327,6 +1330,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->db_create_options= db_create_options= uint2korr(frm_image+30);
share->db_options_in_use= share->db_create_options;
share->mysql_version= uint4korr(frm_image+51);
+ share->table_type= TABLE_TYPE_NORMAL;
share->null_field_first= 0;
if (!frm_image[32]) // New frm file in 3.23
{
@@ -1340,6 +1344,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
enum_value_with_check(thd, share, "transactional", frm_image[39] & 3, HA_CHOICE_MAX);
share->page_checksum= (ha_choice)
enum_value_with_check(thd, share, "page_checksum", (frm_image[39] >> 2) & 3, HA_CHOICE_MAX);
+ if (((ha_choice) enum_value_with_check(thd, share, "sequence",
+ (frm_image[39] >> 4) & 3,
+ HA_CHOICE_MAX)) == HA_CHOICE_YES)
+ {
+ share->table_type= TABLE_TYPE_SEQUENCE;
+ share->sequence= new (&share->mem_root) SEQUENCE();
+ share->non_determinstic_insert= true;
+ }
share->row_type= (enum row_type)
enum_value_with_check(thd, share, "row_format", frm_image[40], ROW_TYPE_MAX);
@@ -1425,7 +1437,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (next_chunk + 2 < buff_end)
{
uint str_db_type_length= uint2korr(next_chunk);
- LEX_STRING name;
+ LEX_CSTRING name;
name.str= (char*) next_chunk + 2;
name.length= str_db_type_length;
@@ -1472,7 +1484,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
else if (!tmp_plugin)
{
/* purecov: begin inspected */
- name.str[name.length]=0;
+ ((char*) name.str)[name.length]=0;
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
goto err;
/* purecov: end */
@@ -1523,7 +1535,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
if (keyinfo->flags & HA_USES_PARSER)
{
- LEX_STRING parser_name;
+ LEX_CSTRING parser_name;
if (next_chunk >= buff_end)
{
DBUG_PRINT("error",
@@ -1736,10 +1748,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
enum_field_types field_type;
CHARSET_INFO *charset=NULL;
Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
- LEX_STRING comment;
+ LEX_CSTRING comment;
+ LEX_CSTRING name;
Virtual_column_info *vcol_info= 0;
uint gis_length, gis_decimals, srid= 0;
Field::utype unireg_check;
+ const Type_handler *handler;
if (new_frm_ver >= 3)
{
@@ -1951,12 +1965,16 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
/* Convert pre-10.2.2 timestamps to use Field::default_value */
unireg_check= (Field::utype) MTYP_TYPENR(unireg_type);
+ name.str= fieldnames.type_names[i];
+ name.length= strlen(name.str);
+ if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
+ goto err; // Not supported field type
*field_ptr= reg_field=
make_field(share, &share->mem_root, record+recpos, (uint32) field_length,
- null_pos, null_bit_pos, pack_flag, field_type, charset,
+ null_pos, null_bit_pos, pack_flag, handler, charset,
geom_type, srid, unireg_check,
(interval_nr ? share->intervals+interval_nr-1 : NULL),
- share->fieldnames.type_names[i]);
+ &name);
if (!reg_field) // Not supported field type
goto err;
@@ -1989,8 +2007,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (vcol_info)
{
- vcol_info->name.str= const_cast<char*>(reg_field->field_name);
- vcol_info->name.length = strlen(reg_field->field_name);
+ vcol_info->name= reg_field->field_name;
if (mysql57_null_bits && !vcol_info->stored_in_db)
{
/* MySQL 5.7 has null bits last */
@@ -2409,18 +2426,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
DBUG_ASSERT(field_nr < share->fields);
reg_field= share->field[field_nr];
}
+ else
+ reg_field= 0; // Safety
vcol_screen_pos+= FRM_VCOL_NEW_HEADER_SIZE;
vcol_info->set_vcol_type((enum_vcol_info_type) type);
- vcol_info->name.length= name_length;
if (name_length)
+ {
vcol_info->name.str= strmake_root(&share->mem_root,
(char*)vcol_screen_pos, name_length);
- else
- {
- vcol_info->name.str= const_cast<char*>(reg_field->field_name);
- vcol_info->name.length = strlen(reg_field->field_name);
+ vcol_info->name.length= name_length;
}
+ else
+ vcol_info->name= reg_field->field_name;
vcol_screen_pos+= name_length + expr_length;
switch (type) {
@@ -2576,7 +2594,8 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
HA_CREATE_INFO *create_info= &lex->create_info;
// ... not CREATE TABLE
- if (lex->sql_command != SQLCOM_CREATE_TABLE)
+ if (lex->sql_command != SQLCOM_CREATE_TABLE &&
+ lex->sql_command != SQLCOM_CREATE_SEQUENCE)
return 1;
// ... create like
if (lex->create_info.like())
@@ -2651,7 +2670,7 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
else
thd->set_n_backup_active_arena(arena, &backup);
- thd->reset_db(db.str, db.length);
+ thd->reset_db((char*) db.str, db.length);
lex_start(thd);
if ((error= parse_sql(thd, & parser_state, NULL) ||
@@ -3045,6 +3064,17 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
DBUG_ASSERT(!db_stat);
}
+ if (share->sequence && outparam->file)
+ {
+ ha_sequence *file;
+ /* SEQUENCE table. Create a sequence handler over the original handler */
+ if (!(file= (ha_sequence*) sql_sequence_hton->create(sql_sequence_hton, share,
+ &outparam->mem_root)))
+ goto err;
+ file->register_original_handler(outparam->file);
+ outparam->file= file;
+ }
+
outparam->reginfo.lock_type= TL_UNLOCK;
outparam->current_lock= F_UNLCK;
records=0;
@@ -3578,30 +3608,6 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
} /* fix_type_pointers */
-TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
-{
- TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
- if (!result)
- return 0;
- result->count=strings.elements;
- result->name="";
- uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
- if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
- return 0;
- result->type_lengths= (uint*) (result->type_names + result->count + 1);
- List_iterator<String> it(strings);
- String *tmp;
- for (uint i=0; (tmp=it++) ; i++)
- {
- result->type_names[i]= tmp->ptr();
- result->type_lengths[i]= tmp->length();
- }
- result->type_names[result->count]= 0; // End marker
- result->type_lengths[result->count]= 0;
- return result;
-}
-
-
/*
Search after a field with given start & length
If an exact field isn't found, return longest field with starts
@@ -3763,7 +3769,8 @@ void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo,
create_info->default_table_charset->number : 0);
fileinfo[38]= (uchar) csid;
fileinfo[39]= (uchar) ((uint) create_info->transactional |
- ((uint) create_info->page_checksum << 2));
+ ((uint) create_info->page_checksum << 2) |
+ ((create_info->sequence ? HA_CHOICE_YES : 0) << 4));
fileinfo[40]= (uchar) create_info->row_type;
/* Bytes 41-46 were for RAID support; now reused for other purposes */
fileinfo[41]= (uchar) (csid >> 8);
@@ -3800,6 +3807,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table)
create_info->transactional= share->transactional;
create_info->page_checksum= share->page_checksum;
create_info->option_list= share->option_list;
+ create_info->sequence= MY_TEST(share->sequence);
DBUG_VOID_RETURN;
}
@@ -3972,7 +3980,6 @@ bool check_table_name(const char *name, size_t length, bool check_for_path_chars
size_t name_length= 0;
const char *end= name+length;
-
if (!check_for_path_chars &&
(check_for_path_chars= check_mysql50_prefix(name)))
{
@@ -4123,7 +4130,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
{
Field *field= table->field[i];
- if (strncmp(field->field_name, field_def->name.str,
+ if (strncmp(field->field_name.str, field_def->name.str,
field_def->name.length))
{
/*
@@ -4135,7 +4142,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
"expected column '%s' at position %d, found '%s'.",
table->s->db.str, table->alias.c_ptr(),
field_def->name.str, i,
- field->field_name);
+ field->field_name.str);
}
field->sql_type(sql_type);
/*
@@ -4553,10 +4560,13 @@ bool TABLE::fill_item_list(List<Item> *item_list) const
is the same as the number of columns in the table.
*/
-void TABLE::reset_item_list(List<Item> *item_list) const
+void TABLE::reset_item_list(List<Item> *item_list, uint skip) const
{
List_iterator_fast<Item> it(*item_list);
- for (Field **ptr= field; *ptr; ptr++)
+ Field **ptr= field;
+ for ( ; skip && *ptr; skip--)
+ ptr++;
+ for (; *ptr; ptr++)
{
Item_field *item_field= (Item_field*) it++;
DBUG_ASSERT(item_field != 0);
@@ -4572,7 +4582,7 @@ void TABLE::reset_item_list(List<Item> *item_list) const
buffer buffer for md5 writing
*/
-void TABLE_LIST::calc_md5(char *buffer)
+void TABLE_LIST::calc_md5(const char *buffer)
{
uchar digest[16];
compute_md5_hash(digest, select_stmt.str,
@@ -4660,8 +4670,9 @@ bool TABLE_LIST::create_field_translation(THD *thd)
while ((item= it++))
{
- DBUG_ASSERT(item->name && item->name[0]);
- transl[field_count].name= thd->strdup(item->name);
+ DBUG_ASSERT(item->name.str && item->name.str[0]);
+ transl[field_count].name.str= thd->strmake(item->name.str, item->name.length);
+ transl[field_count].name.length= item->name.length;
transl[field_count++].item= item;
}
field_translation= transl;
@@ -5486,7 +5497,7 @@ bool TABLE_LIST::prepare_security(THD *thd)
while ((tbl= tb++))
{
DBUG_ASSERT(tbl->referencing_view);
- char *local_db, *local_table_name;
+ const char *local_db, *local_table_name;
if (tbl->view)
{
local_db= tbl->view_db.str;
@@ -5611,15 +5622,15 @@ Natural_join_column::Natural_join_column(Item_field *field_param,
}
-const char *Natural_join_column::name()
+LEX_CSTRING *Natural_join_column::name()
{
if (view_field)
{
DBUG_ASSERT(table_field == NULL);
- return view_field->name;
+ return &view_field->name;
}
- return table_field->field_name;
+ return &table_field->field_name;
}
@@ -5629,7 +5640,7 @@ Item *Natural_join_column::create_item(THD *thd)
{
DBUG_ASSERT(table_field == NULL);
return create_view_field(thd, table_ref, &view_field->item,
- view_field->name);
+ &view_field->name);
}
return table_field;
}
@@ -5698,9 +5709,9 @@ void Field_iterator_view::set(TABLE_LIST *table)
}
-const char *Field_iterator_table::name()
+LEX_CSTRING *Field_iterator_table::name()
{
- return (*ptr)->field_name;
+ return &(*ptr)->field_name;
}
@@ -5709,6 +5720,7 @@ Item *Field_iterator_table::create_item(THD *thd)
SELECT_LEX *select= thd->lex->current_select;
Item_field *item= new (thd->mem_root) Item_field(thd, &select->context, *ptr);
+ DBUG_ASSERT(strlen(item->name.str) == item->name.length);
if (item && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
!thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS)
{
@@ -5720,19 +5732,19 @@ Item *Field_iterator_table::create_item(THD *thd)
}
-const char *Field_iterator_view::name()
+LEX_CSTRING *Field_iterator_view::name()
{
- return ptr->name;
+ return &ptr->name;
}
Item *Field_iterator_view::create_item(THD *thd)
{
- return create_view_field(thd, view, &ptr->item, ptr->name);
+ return create_view_field(thd, view, &ptr->item, &ptr->name);
}
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
- const char *name)
+ LEX_CSTRING *name)
{
bool save_wrapper= thd->lex->select_lex.no_wrap_view_item;
Item *field= *field_ref;
@@ -7390,7 +7402,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
DBUG_ASSERT(vcol_info);
DBUG_ASSERT(vcol_info->expr);
- bool update, swap_values= 0;
+ bool update= 0, swap_values= 0;
switch (update_mode) {
case VCOL_UPDATE_FOR_READ:
update= !vcol_info->stored_in_db
@@ -7434,7 +7446,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
if (vcol_info->expr->save_in_field(vf, 0))
field_error= error= 1;
DBUG_PRINT("info", ("field '%s' - updated error: %d",
- vf->field_name, field_error));
+ vf->field_name.str, field_error));
if (swap_values && (vf->flags & BLOB_FLAG))
{
/*
@@ -7448,7 +7460,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
}
else
{
- DBUG_PRINT("info", ("field '%s' - skipped", vf->field_name));
+ DBUG_PRINT("info", ("field '%s' - skipped", vf->field_name.str));
}
}
if (handler_pushed)
@@ -7522,7 +7534,7 @@ int TABLE::update_default_fields(bool update_command, bool ignore_errors)
res|= field->evaluate_update_default_function();
if (!ignore_errors && res)
{
- my_error(ER_CALCULATING_DEFAULT_VALUE, MYF(0), field->field_name);
+ my_error(ER_CALCULATING_DEFAULT_VALUE, MYF(0), field->field_name.str);
break;
}
res= 0;
@@ -7944,7 +7956,7 @@ int TABLE_LIST::fetch_number_of_rows()
if (is_materialized_derived() && !fill_me)
{
- table->file->stats.records= ((select_union*)derived->result)->records;
+ table->file->stats.records= ((select_unit*)derived->result)->records;
set_if_bigger(table->file->stats.records, 2);
table->used_stat_records= table->file->stats.records;
}
@@ -8277,3 +8289,38 @@ LEX_CSTRING *fk_option_name(enum_fk_option opt)
};
return names + opt;
}
+
+
+Field *TABLE::find_field_by_name(LEX_CSTRING *str) const
+{
+ uint length= str->length;
+ for (Field **tmp= field; *tmp; tmp++)
+ {
+ if ((*tmp)->field_name.length == length &&
+ !my_strcasecmp(system_charset_info, (*tmp)->field_name.str, str->str))
+ return *tmp;
+ }
+ return NULL;
+}
+
+
+bool TABLE::export_structure(THD *thd, Row_definition_list *defs)
+{
+ for (Field **src= field; *src; src++)
+ {
+ uint offs;
+ if (defs->find_row_field_by_name(&src[0]->field_name, &offs))
+ {
+ my_error(ER_DUP_FIELDNAME, MYF(0), src[0]->field_name.str);
+ return true;
+ }
+ Spvar_definition *def= new (thd->mem_root) Spvar_definition(thd, *src);
+ if (!def)
+ return true;
+ def->flags&= (uint) ~NOT_NULL_FLAG;
+ if ((def->sp_prepare_create_field(thd, thd->mem_root)) ||
+ (defs->push_back(def, thd->mem_root)))
+ return true;
+ }
+ return false;
+}
diff --git a/sql/table.h b/sql/table.h
index 22846e05bde..c502b6bddf8 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -54,6 +54,7 @@ struct TDC_element;
class Virtual_column_info;
class Table_triggers_list;
class TMP_TABLE_PARAM;
+class SEQUENCE;
/*
Used to identify NESTED_JOIN structures within a join (applicable only to
@@ -448,15 +449,15 @@ enum enum_table_category
};
typedef enum enum_table_category TABLE_CATEGORY;
-TABLE_CATEGORY get_table_category(const LEX_STRING *db,
- const LEX_STRING *name);
+TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
+ const LEX_CSTRING *name);
typedef struct st_table_field_type
{
- LEX_STRING name;
- LEX_STRING type;
- LEX_STRING cset;
+ LEX_CSTRING name;
+ LEX_CSTRING type;
+ LEX_CSTRING cset;
} TABLE_FIELD_TYPE;
@@ -600,7 +601,7 @@ struct TABLE_SHARE
TABLE_STATISTICS_CB stats_cb;
uchar *default_values; /* row with default values */
- LEX_STRING comment; /* Comment about table */
+ LEX_CSTRING comment; /* Comment about table */
CHARSET_INFO *table_charset; /* Default charset of string fields */
MY_BITMAP *check_set; /* Fields used by check constrant */
@@ -615,12 +616,12 @@ struct TABLE_SHARE
should correspond to each other.
To ensure this one can use set_table_cache() methods.
*/
- LEX_STRING table_cache_key;
- LEX_STRING db; /* Pointer to db */
- LEX_STRING table_name; /* Table name (for open) */
- LEX_STRING path; /* Path to .frm file (from datadir) */
- LEX_STRING normalized_path; /* unpack_filename(path) */
- LEX_STRING connect_string;
+ LEX_CSTRING table_cache_key;
+ LEX_CSTRING db; /* Pointer to db */
+ LEX_CSTRING table_name; /* Table name (for open) */
+ LEX_CSTRING path; /* Path to .frm file (from datadir) */
+ LEX_CSTRING normalized_path; /* unpack_filename(path) */
+ LEX_CSTRING connect_string;
/*
Set of keys in use, implemented as a Bitmap.
@@ -642,6 +643,7 @@ struct TABLE_SHARE
db_plugin ? plugin_hton(db_plugin) : NULL;
}
enum row_type row_type; /* How rows are stored */
+ enum Table_type table_type;
enum tmp_table_type tmp_table;
/** Transactional or not. */
@@ -716,6 +718,9 @@ struct TABLE_SHARE
*/
const File_parser *view_def;
+ /* For sequence tables, the current sequence state */
+ SEQUENCE *sequence;
+
/*
Cache for row-based replication table share checks that does not
need to be repeated. Possible values are: -1 when cache value is
@@ -1303,7 +1308,7 @@ public:
void init(THD *thd, TABLE_LIST *tl);
bool fill_item_list(List<Item> *item_list) const;
- void reset_item_list(List<Item> *item_list) const;
+ void reset_item_list(List<Item> *item_list, uint skip) const;
void clear_column_bitmaps(void);
void prepare_for_position(void);
MY_BITMAP *prepare_for_keyread(uint index, MY_BITMAP *map);
@@ -1440,6 +1445,8 @@ public:
TABLE *tmp_table,
TMP_TABLE_PARAM *tmp_table_param,
bool with_cleanup);
+ Field *find_field_by_name(LEX_CSTRING *str) const;
+ bool export_structure(THD *thd, class Row_definition_list *defs);
};
@@ -1486,16 +1493,16 @@ enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
typedef struct st_foreign_key_info
{
- LEX_STRING *foreign_id;
- LEX_STRING *foreign_db;
- LEX_STRING *foreign_table;
- LEX_STRING *referenced_db;
- LEX_STRING *referenced_table;
+ LEX_CSTRING *foreign_id;
+ LEX_CSTRING *foreign_db;
+ LEX_CSTRING *foreign_table;
+ LEX_CSTRING *referenced_db;
+ LEX_CSTRING *referenced_table;
enum_fk_option update_method;
enum_fk_option delete_method;
- LEX_STRING *referenced_key_name;
- List<LEX_STRING> foreign_fields;
- List<LEX_STRING> referenced_fields;
+ LEX_CSTRING *referenced_key_name;
+ List<LEX_CSTRING> foreign_fields;
+ List<LEX_CSTRING> referenced_fields;
} FOREIGN_KEY_INFO;
LEX_CSTRING *fk_option_name(enum_fk_option opt);
@@ -1558,7 +1565,8 @@ typedef struct st_schema_table
/* Handle fileds for old SHOW */
int (*old_format) (THD *thd, struct st_schema_table *schema_table);
int (*process_table) (THD *thd, TABLE_LIST *tables, TABLE *table,
- bool res, LEX_STRING *db_name, LEX_STRING *table_name);
+ bool res, const LEX_CSTRING *db_name,
+ const LEX_CSTRING *table_name);
int idx_field1, idx_field2;
bool hidden;
uint i_s_requested_object; /* the object we need to open(TABLE | VIEW) */
@@ -1618,10 +1626,6 @@ class IS_table_read_plan;
#define JOIN_TYPE_RIGHT 2U
#define JOIN_TYPE_OUTER 4U /* Marker that this is an outer join */
-#define VIEW_SUID_INVOKER 0
-#define VIEW_SUID_DEFINER 1
-#define VIEW_SUID_DEFAULT 2
-
/* view WITH CHECK OPTION parameter options */
#define VIEW_CHECK_NONE 0
#define VIEW_CHECK_LOCAL 1
@@ -1635,16 +1639,16 @@ class IS_table_read_plan;
/** The threshold size a blob field buffer before it is freed */
#define MAX_TDC_BLOB_SIZE 65536
-class select_union;
+class select_unit;
class TMP_TABLE_PARAM;
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
- const char *name);
+ LEX_CSTRING *name);
struct Field_translator
{
Item *item;
- const char *name;
+ LEX_CSTRING name;
};
@@ -1671,7 +1675,7 @@ public:
public:
Natural_join_column(Field_translator *field_param, TABLE_LIST *tab);
Natural_join_column(Item_field *field_param, TABLE_LIST *tab);
- const char *name();
+ LEX_CSTRING *name();
Item *create_item(THD *thd);
Field *field();
const char *table_name();
@@ -1792,8 +1796,8 @@ struct TABLE_LIST
TABLE_LIST *next_local;
/* link in a global list of all queries tables */
TABLE_LIST *next_global, **prev_global;
- char *db, *alias, *table_name, *schema_table_name;
- char *option; /* Used by cache index */
+ const char *db, *alias, *table_name, *schema_table_name;
+ const char *option; /* Used by cache index */
Item *on_expr; /* Used with outer join */
Item *sj_on_expr;
@@ -1868,7 +1872,7 @@ struct TABLE_LIST
select_result for derived table to pass it from table creation to table
filling procedure
*/
- select_union *derived_result;
+ select_unit *derived_result;
/* Stub used for materialized derived tables. */
table_map map; /* ID bit of table (1,2,4,8,16...) */
table_map get_map()
@@ -1984,12 +1988,12 @@ struct TABLE_LIST
Item *where; /* VIEW WHERE clause condition */
Item *check_option; /* WITH CHECK OPTION condition */
LEX_STRING select_stmt; /* text of (CREATE/SELECT) statement */
- LEX_STRING md5; /* md5 of query text */
- LEX_STRING source; /* source of CREATE VIEW */
- LEX_STRING view_db; /* saved view database */
- LEX_STRING view_name; /* saved view name */
+ LEX_CSTRING md5; /* md5 of query text */
+ LEX_CSTRING source; /* source of CREATE VIEW */
+ LEX_CSTRING view_db; /* saved view database */
+ LEX_CSTRING view_name; /* saved view name */
LEX_STRING timestamp; /* GMT time stamp of last operation */
- st_lex_user definer; /* definer of view */
+ LEX_USER definer; /* definer of view */
ulonglong file_version; /* version of file's field set */
ulonglong mariadb_version; /* version of server on creation */
ulonglong updatable_view; /* VIEW can be updated */
@@ -2056,8 +2060,8 @@ struct TABLE_LIST
bool where_processed;
/* TRUE <=> VIEW CHECK OPTION expression has been processed */
bool check_option_processed;
- /* FRMTYPE_ERROR if any type is acceptable */
- enum frm_type_enum required_type;
+ /* TABLE_TYPE_UNKNOWN if any type is acceptable */
+ Table_type required_type;
handlerton *db_type; /* table_type for handler */
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
/*
@@ -2096,6 +2100,7 @@ struct TABLE_LIST
bool merged_for_insert;
/* TRUE <=> don't prepare this derived table/view as it should be merged.*/
bool skip_prepare_derived;
+ bool sequence; /* Part of NEXTVAL/CURVAL/LASTVAL */
/*
Items created by create_view_field and collected to change them in case
@@ -2120,8 +2125,8 @@ struct TABLE_LIST
These attributes MUST NOT be used for any purposes but the parsing.
*/
- LEX_STRING view_client_cs_name;
- LEX_STRING view_connection_cl_name;
+ LEX_CSTRING view_client_cs_name;
+ LEX_CSTRING view_connection_cl_name;
/*
View definition (SELECT-statement) in the UTF-form.
@@ -2171,7 +2176,7 @@ struct TABLE_LIST
List<String> *partition_names;
#endif /* WITH_PARTITION_STORAGE_ENGINE */
- void calc_md5(char *buffer);
+ void calc_md5(const char *buffer);
int view_check_option(THD *thd, bool ignore_failure);
bool create_field_translation(THD *thd);
bool setup_underlying(THD *thd);
@@ -2354,7 +2359,7 @@ struct TABLE_LIST
@brief Returns the name of the database that the referenced table belongs
to.
*/
- char *get_db_name() const { return view != NULL ? view_db.str : db; }
+ const char *get_db_name() const { return view != NULL ? view_db.str : db; }
/**
@brief Returns the name of the table that this TABLE_LIST represents.
@@ -2362,7 +2367,7 @@ struct TABLE_LIST
@details The unqualified table name or view name for a table or view,
respectively.
*/
- char *get_table_name() const { return view != NULL ? view_name.str : table_name; }
+ const char *get_table_name() const { return view != NULL ? view_name.str : table_name; }
bool is_active_sjm();
bool is_jtbm() { return MY_TEST(jtbm_subselect != NULL); }
st_select_lex_unit *get_unit();
@@ -2416,7 +2421,7 @@ public:
virtual void set(TABLE_LIST *)= 0;
virtual void next()= 0;
virtual bool end_of_fields()= 0; /* Return 1 at end of list */
- virtual const char *name()= 0;
+ virtual LEX_CSTRING *name()= 0;
virtual Item *create_item(THD *)= 0;
virtual Field *field()= 0;
};
@@ -2436,7 +2441,7 @@ public:
void set_table(TABLE *table) { ptr= table->field; }
void next() { ptr++; }
bool end_of_fields() { return *ptr == 0; }
- const char *name();
+ LEX_CSTRING *name();
Item *create_item(THD *thd);
Field *field() { return *ptr; }
};
@@ -2453,7 +2458,7 @@ public:
void set(TABLE_LIST *table);
void next() { ptr++; }
bool end_of_fields() { return ptr == array_end; }
- const char *name();
+ LEX_CSTRING *name();
Item *create_item(THD *thd);
Item **item_ptr() {return &ptr->item; }
Field *field() { return 0; }
@@ -2477,7 +2482,7 @@ public:
void set(TABLE_LIST *table);
void next();
bool end_of_fields() { return !cur_column_ref; }
- const char *name() { return cur_column_ref->name(); }
+ LEX_CSTRING *name() { return cur_column_ref->name(); }
Item *create_item(THD *thd) { return cur_column_ref->create_item(thd); }
Field *field() { return cur_column_ref->field(); }
Natural_join_column *column_ref() { return cur_column_ref; }
@@ -2514,7 +2519,7 @@ public:
void next();
bool end_of_fields()
{ return (table_ref == last_leaf && field_it->end_of_fields()); }
- const char *name() { return field_it->name(); }
+ LEX_CSTRING *name() { return field_it->name(); }
const char *get_table_name();
const char *get_db_name();
GRANT_INFO *grant();
@@ -2695,7 +2700,7 @@ int rename_file_ext(const char * from,const char * to,const char * ext);
char *get_field(MEM_ROOT *mem, Field *field);
bool get_field(MEM_ROOT *mem, Field *field, class String *res);
-bool validate_comment_length(THD *thd, LEX_STRING *comment, size_t max_len,
+bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
uint err_code, const char *name);
int closefrm(TABLE *table);
@@ -2718,14 +2723,14 @@ static inline int set_zone(int nr,int min_zone,int max_zone)
}
/* performance schema */
-extern LEX_STRING PERFORMANCE_SCHEMA_DB_NAME;
+extern LEX_CSTRING PERFORMANCE_SCHEMA_DB_NAME;
-extern LEX_STRING GENERAL_LOG_NAME;
-extern LEX_STRING SLOW_LOG_NAME;
+extern LEX_CSTRING GENERAL_LOG_NAME;
+extern LEX_CSTRING SLOW_LOG_NAME;
/* information schema */
-extern LEX_STRING INFORMATION_SCHEMA_NAME;
-extern LEX_STRING MYSQL_SCHEMA_NAME;
+extern LEX_CSTRING INFORMATION_SCHEMA_NAME;
+extern LEX_CSTRING MYSQL_SCHEMA_NAME;
inline bool is_infoschema_db(const char *name, size_t len)
{
@@ -2740,7 +2745,6 @@ inline bool is_infoschema_db(const char *name)
INFORMATION_SCHEMA_NAME.str, name);
}
-TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
inline void mark_as_null_row(TABLE *table)
{
diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc
index 42ebb87cbe4..0fc5150cfe1 100644
--- a/sql/temporary_tables.cc
+++ b/sql/temporary_tables.cc
@@ -73,7 +73,9 @@ TABLE *THD::create_and_open_tmp_table(handlerton *hton,
if ((share= create_temporary_table(hton, frm, path, db, table_name)))
{
+ open_options|= HA_OPEN_FOR_CREATE;
table= open_temporary_table(share, table_name, open_in_engine);
+ open_options&= ~HA_OPEN_FOR_CREATE;
/*
Failed to open a temporary table instance. As we are not passing
@@ -1103,8 +1105,10 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share,
if (open_table_from_share(this, share, alias,
open_in_engine ? (uint)HA_OPEN_KEYFILE : 0,
- EXTRA_RECORD, ha_open_options, table,
- open_in_engine ? false : true))
+ EXTRA_RECORD,
+ (ha_open_options |
+ (open_options & HA_OPEN_FOR_CREATE)),
+ table, open_in_engine ? false : true))
{
my_free(table);
DBUG_RETURN(NULL);
@@ -1112,7 +1116,7 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share,
table->reginfo.lock_type= TL_WRITE; /* Simulate locked */
table->grant.privilege= TMP_TABLE_ACLS;
- share->tmp_table= (table->file->has_transactions() ?
+ share->tmp_table= (table->file->has_transaction_manager() ?
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
table->pos_in_table_list= 0;
diff --git a/sql/transaction.cc b/sql/transaction.cc
index d01519b8bd4..78cd3047f82 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -576,7 +576,7 @@ bool trans_rollback_stmt(THD *thd)
/* Find a named savepoint in the current transaction. */
static SAVEPOINT **
-find_savepoint(THD *thd, LEX_STRING name)
+find_savepoint(THD *thd, LEX_CSTRING name)
{
SAVEPOINT **sv= &thd->transaction.savepoints;
@@ -602,7 +602,7 @@ find_savepoint(THD *thd, LEX_STRING name)
@retval TRUE Failure
*/
-bool trans_savepoint(THD *thd, LEX_STRING name)
+bool trans_savepoint(THD *thd, LEX_CSTRING name)
{
SAVEPOINT **sv, *newsv;
DBUG_ENTER("trans_savepoint");
@@ -679,7 +679,7 @@ bool trans_savepoint(THD *thd, LEX_STRING name)
@retval TRUE Failure
*/
-bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name)
+bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name)
{
int res= FALSE;
SAVEPOINT *sv= *find_savepoint(thd, name);
@@ -756,7 +756,7 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name)
@retval TRUE Failure
*/
-bool trans_release_savepoint(THD *thd, LEX_STRING name)
+bool trans_release_savepoint(THD *thd, LEX_CSTRING name)
{
int res= FALSE;
SAVEPOINT *sv= *find_savepoint(thd, name);
diff --git a/sql/transaction.h b/sql/transaction.h
index 90de11aabe3..b6b22053150 100644
--- a/sql/transaction.h
+++ b/sql/transaction.h
@@ -34,9 +34,9 @@ bool trans_rollback_implicit(THD *thd);
bool trans_commit_stmt(THD *thd);
bool trans_rollback_stmt(THD *thd);
-bool trans_savepoint(THD *thd, LEX_STRING name);
-bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name);
-bool trans_release_savepoint(THD *thd, LEX_STRING name);
+bool trans_savepoint(THD *thd, LEX_CSTRING name);
+bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name);
+bool trans_release_savepoint(THD *thd, LEX_CSTRING name);
bool trans_xa_start(THD *thd);
bool trans_xa_end(THD *thd);
diff --git a/sql/udf_example.c b/sql/udf_example.c
index a48801d1c4a..6a0d78078a6 100644
--- a/sql/udf_example.c
+++ b/sql/udf_example.c
@@ -56,7 +56,7 @@
**
** Function 'myfunc_int' returns summary length of all its arguments.
**
-** Function 'sequence' returns an sequence starting from a certain number.
+** Function 'udf_sequence' returns an sequence starting from a certain number.
**
** Function 'myfunc_argument_name' returns name of argument.
**
@@ -80,7 +80,7 @@
** CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
** CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
** CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
-** CREATE FUNCTION sequence RETURNS INTEGER SONAME "udf_example.so";
+** CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "udf_example.so";
** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
** CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";
@@ -162,9 +162,9 @@ double myfunc_double(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
my_bool myfunc_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
longlong myfunc_int(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error);
-my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
- void sequence_deinit(UDF_INIT *initid);
-longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
+my_bool udf_sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
+ void udf_sequence_deinit(UDF_INIT *initid);
+longlong udf_sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error);
my_bool avgcost_init( UDF_INIT* initid, UDF_ARGS* args, char* message );
void avgcost_deinit( UDF_INIT* initid );
@@ -642,7 +642,7 @@ my_bool myfunc_int_init(UDF_INIT *initid __attribute__((unused)),
or 1 if no arguments have been given
*/
-my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+my_bool udf_sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if (args->arg_count > 1)
{
@@ -659,22 +659,22 @@ my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
}
bzero(initid->ptr,sizeof(longlong));
/*
- sequence() is a non-deterministic function : it has different value
+ udf_sequence() is a non-deterministic function : it has different value
even if called with the same arguments.
*/
initid->const_item=0;
return 0;
}
-void sequence_deinit(UDF_INIT *initid)
+void udf_sequence_deinit(UDF_INIT *initid)
{
if (initid->ptr)
free(initid->ptr);
}
-longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
- char *is_null __attribute__((unused)),
- char *error __attribute__((unused)))
+longlong udf_sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
+ char *is_null __attribute__((unused)),
+ char *error __attribute__((unused)))
{
ulonglong val=0;
if (args->arg_count)
diff --git a/sql/udf_example.def b/sql/udf_example.def
index 41150b24e8f..74230b638bf 100644
--- a/sql/udf_example.def
+++ b/sql/udf_example.def
@@ -14,9 +14,9 @@ EXPORTS
myfunc_double
myfunc_int_init
myfunc_int
- sequence_init
- sequence_deinit
- sequence
+ udf_sequence_init
+ udf_sequence_deinit
+ udf_sequence
avgcost_init
avgcost_deinit
avgcost_reset
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 0bb8a4e77c6..655cfa20c61 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -73,7 +73,7 @@ static uchar *extra2_write_len(uchar *pos, size_t len)
}
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
- LEX_STRING *str)
+ const LEX_CSTRING *str)
{
*pos++ = type;
pos= extra2_write_len(pos, str->length);
@@ -84,7 +84,7 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
LEX_CUSTRING *str)
{
- return extra2_write(pos, type, reinterpret_cast<LEX_STRING *>(str));
+ return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str));
}
/**
@@ -107,7 +107,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
List<Create_field> &create_fields,
uint keys, KEY *key_info, handler *db_file)
{
- LEX_STRING str_db_type;
+ LEX_CSTRING str_db_type;
uint reclength, key_info_length, i;
ulong key_buff_length;
ulong filepos, data_offset;
@@ -616,7 +616,8 @@ static bool pack_header(THD *thd, uchar *forminfo,
while ((field=it++))
{
if (validate_comment_length(thd, &field->comment, COLUMN_COMMENT_MAXLEN,
- ER_TOO_LONG_FIELD_COMMENT, field->field_name))
+ ER_TOO_LONG_FIELD_COMMENT,
+ field->field_name.str))
DBUG_RETURN(1);
totlength+= field->length;
@@ -625,14 +626,14 @@ static bool pack_header(THD *thd, uchar *forminfo,
We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
as auto-update field.
*/
- if (field->sql_type == MYSQL_TYPE_TIMESTAMP &&
+ if (field->real_field_type() == MYSQL_TYPE_TIMESTAMP &&
MTYP_TYPENR(field->unireg_check) != Field::NONE &&
!time_stamp_pos)
time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
length=field->pack_length;
if ((uint) field->offset+ (uint) data_offset+ length > reclength)
reclength=(uint) (field->offset+ data_offset + length);
- n_length+= (ulong) strlen(field->field_name)+1;
+ n_length+= field->field_name.length + 1;
field->interval_id=0;
field->save_interval= 0;
if (field->interval)
@@ -776,7 +777,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields)
}
length+= FCOMP;
- length+= strlen(field->field_name)+1;
+ length+= field->field_name.length + 1;
length+= field->comment.length;
}
length+= 2;
@@ -807,8 +808,8 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
int2store(buff+8,field->pack_flag);
buff[10]= (uchar) field->unireg_check;
buff[12]= (uchar) field->interval_id;
- buff[13]= (uchar) field->sql_type;
- if (field->sql_type == MYSQL_TYPE_GEOMETRY)
+ buff[13]= (uchar) field->real_field_type();
+ if (field->real_field_type() == MYSQL_TYPE_GEOMETRY)
{
buff[11]= 0;
buff[14]= (uchar) field->geom_type;
@@ -837,7 +838,7 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
it.rewind();
while ((field=it++))
{
- buff= (uchar*)strmov((char*) buff, field->field_name);
+ buff= (uchar*)strmov((char*) buff, field->field_name.str);
*buff++=NAMES_SEP_CHAR;
}
*buff++= 0;
@@ -953,13 +954,13 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
null_pos + null_count / 8,
null_count & 7,
field->pack_flag,
- field->sql_type,
+ field->type_handler(),
field->charset,
field->geom_type, field->srid,
field->unireg_check,
field->save_interval ? field->save_interval
: field->interval,
- field->field_name);
+ &field->field_name);
if (!regfield)
{
error= 1;
@@ -975,7 +976,8 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
null_count++;
}
- if (field->sql_type == MYSQL_TYPE_BIT && !f_bit_as_char(field->pack_flag))
+ if (field->real_field_type() == MYSQL_TYPE_BIT &&
+ !f_bit_as_char(field->pack_flag))
null_count+= field->length & 7;
if (field->default_value && !field->default_value->flags &&
@@ -989,7 +991,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
/* If not ok or warning of level 'note' */
if (res != 0 && res != 3)
{
- my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name.str);
error= 1;
delete regfield; //To avoid memory leak
goto err;
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index d538383ebc4..ad5ef9c5c55 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -451,8 +451,8 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf,
char filename[PATH_MAX]= {0};
File file;
IO_CACHE cache;
- Log_event_writer writer(&cache);
- Format_description_log_event *ev;
+ Log_event_writer writer(&cache, 0);
+ Format_description_log_event *ev= 0;
int len= my_snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld_v2.log",
wsrep_data_home_dir, (longlong) thd->thread_id,
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index e34f1b92d52..1121bb65fe3 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -95,7 +95,8 @@ void wsrep_register_hton(THD* thd, bool all)
* replicated unless we declare wsrep hton as read/write here
*/
if (i->is_trx_read_write() ||
- (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
+ ((thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
+ thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE) &&
thd->wsrep_exec_mode == LOCAL_STATE))
{
thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write();
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 9a99dffc724..87eb97e4fec 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1245,7 +1245,7 @@ int wsrep_to_buf_helper(
THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len)
{
IO_CACHE tmp_io_cache;
- Log_event_writer writer(&tmp_io_cache);
+ Log_event_writer writer(&tmp_io_cache,0);
if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX,
65536, MYF(MY_WME)))
return 1;
@@ -1331,8 +1331,8 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
{ C_STRING_WITH_LEN("ALTER ") },
{ C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
- buff.append(command[thd->lex->create_view_mode].str,
- command[thd->lex->create_view_mode].length);
+ buff.append(command[thd->lex->create_view->mode].str,
+ command[thd->lex->create_view->mode].length);
LEX_USER *definer;
@@ -1360,9 +1360,9 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
return 1;
}
- views->algorithm = lex->create_view_algorithm;
- views->view_suid = lex->create_view_suid;
- views->with_check = lex->create_view_check;
+ views->algorithm = lex->create_view->algorithm;
+ views->view_suid = lex->create_view->suid;
+ views->with_check = lex->create_view->check;
view_store_options(thd, views, &buff);
buff.append(STRING_WITH_LEN("VIEW "));
@@ -1391,8 +1391,8 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
}
buff.append(STRING_WITH_LEN(" AS "));
//buff.append(views->source.str, views->source.length);
- buff.append(thd->lex->create_view_select.str,
- thd->lex->create_view_select.length);
+ buff.append(thd->lex->create_view->select.str,
+ thd->lex->create_view->select.length);
//int errcode= query_error_code(thd, TRUE);
//if (thd->binlog_query(THD::STMT_QUERY_TYPE,
// buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcod
@@ -1409,7 +1409,7 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
1: TOI replication was skipped
-1: TOI replication failed
*/
-static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
+static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list)
{
wsrep_status_t ret(WSREP_WARNING);
@@ -1473,8 +1473,8 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
ret,
(thd->db ? thd->db : "(null)"),
(thd->query()) ? thd->query() : "void");
- my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check "
- "your wsrep connection state and retry the query.");
+ my_message(ER_LOCK_DEADLOCK, "WSREP replication failed. Check "
+ "your wsrep connection state and retry the query.", MYF(0));
wsrep_keys_free(&key_arr);
rc= -1;
}
@@ -1512,7 +1512,7 @@ static void wsrep_TOI_end(THD *thd) {
}
}
-static int wsrep_RSU_begin(THD *thd, char *db_, char *table_)
+static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
{
wsrep_status_t ret(WSREP_WARNING);
WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
@@ -1595,7 +1595,7 @@ static void wsrep_RSU_end(THD *thd)
thd->variables.wsrep_on = 1;
}
-int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
+int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list)
{
int ret= 0;
@@ -1781,7 +1781,8 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
/* Print some debug information. */
if (wsrep_debug)
{
- if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE)
+ if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE ||
+ request_thd->lex->sql_command == SQLCOM_DROP_SEQUENCE)
{
WSREP_DEBUG("DROP caused BF abort");
}
@@ -2252,7 +2253,7 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
sp->m_params.str, sp->m_params.length,
retstr.c_ptr(), retstr.length(),
sp->m_body.str, sp->m_body.length,
- sp->m_chistics, &(thd->lex->definer->user),
+ sp->chistics(), &(thd->lex->definer->user),
&(thd->lex->definer->host),
saved_mode))
{
@@ -2548,8 +2549,8 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
LEX *lex= thd->lex;
String stmt_query;
- LEX_STRING definer_user;
- LEX_STRING definer_host;
+ LEX_CSTRING definer_user;
+ LEX_CSTRING definer_host;
if (!lex->definer)
{
@@ -2586,7 +2587,7 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
append_definer(thd, &stmt_query, &definer_user, &definer_host);
- LEX_STRING stmt_definition;
+ LEX_CSTRING stmt_definition;
uint not_used;
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
stmt_definition.length= thd->lex->stmt_definition_end
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 069801b43e3..7eae366df7a 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -281,7 +281,7 @@ extern PSI_mutex_key key_LOCK_wsrep_desync;
extern PSI_file_key key_file_wsrep_gra_log;
#endif /* HAVE_PSI_INTERFACE */
struct TABLE_LIST;
-int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
+int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list);
void wsrep_to_isolation_end(THD *thd);
void wsrep_cleanup_transaction(THD *thd);
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index ae7208b9579..f8db20ace99 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -103,7 +103,7 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname)
new Format_description_log_event(4);
}
- static LEX_STRING connection_name= { C_STRING_WITH_LEN("wsrep") };
+ static LEX_CSTRING connection_name= { STRING_WITH_LEN("wsrep") };
/*
Master_info's constructor initializes rpl_filter by either an already
@@ -316,7 +316,6 @@ void wsrep_replay_transaction(THD *thd)
else
{
WSREP_DEBUG("replay failed, rolling back");
- //my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction");
}
thd->wsrep_conflict_state= ABORTED;
wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle);
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index b34fdf8b7ed..d7f55dbca60 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -313,7 +313,7 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type)
//when fails
if (wsrep_init())
{
- my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp);
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp, my_error, "wsrep_init failed");
rcode = true;
}
free(tmp);
@@ -614,7 +614,7 @@ bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type)
char max_ws_size_opt[128];
my_snprintf(max_ws_size_opt, sizeof(max_ws_size_opt),
- "repl.max_ws_size=%d", wsrep_max_ws_size);
+ "repl.max_ws_size=%lu", wsrep_max_ws_size);
wsrep_status_t ret= wsrep->options_set(wsrep, max_ws_size_opt);
if (ret != WSREP_OK)
{
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index cc2140e838e..8bf90e700d4 100644
--- a/storage/archive/azio.c
+++ b/storage/archive/azio.c
@@ -913,7 +913,7 @@ int azread_frm(azio_stream *s, uchar *blob)
/*
Simple comment field
*/
-int azwrite_comment(azio_stream *s, char *blob, unsigned int length)
+int azwrite_comment(azio_stream *s, const char *blob, unsigned int length)
{
if (s->mode == 'r')
return 1;
diff --git a/storage/archive/azlib.h b/storage/archive/azlib.h
index 2971705b2f1..d9318002901 100644
--- a/storage/archive/azlib.h
+++ b/storage/archive/azlib.h
@@ -336,7 +336,8 @@ extern int azclose(azio_stream *file);
extern int azwrite_frm (azio_stream *s, const uchar *blob, unsigned int length);
extern int azread_frm (azio_stream *s, uchar *blob);
-extern int azwrite_comment (azio_stream *s, char *blob, unsigned int length);
+extern int azwrite_comment (azio_stream *s, const char *blob,
+ unsigned int length);
extern int azread_comment (azio_stream *s, char *blob);
#ifdef __cplusplus
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 56d8000d64d..ed9b03dc82b 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -105,7 +105,7 @@ int ha_blackhole::write_row(uchar * buf)
DBUG_RETURN(table->next_number_field ? update_auto_increment() : 0);
}
-int ha_blackhole::update_row(const uchar *old_data, uchar *new_data)
+int ha_blackhole::update_row(const uchar *old_data, const uchar *new_data)
{
DBUG_ENTER("ha_blackhole::update_row");
THD *thd= ha_thd();
diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index b70320848d7..9a4b34809f8 100644
--- a/storage/blackhole/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
@@ -97,6 +97,6 @@ public:
enum thr_lock_type lock_type);
private:
virtual int write_row(uchar *buf);
- virtual int update_row(const uchar *old_data, uchar *new_data);
+ virtual int update_row(const uchar *old_data, const uchar *new_data);
virtual int delete_row(const uchar *buf);
};
diff --git a/storage/cassandra/ha_cassandra.cc b/storage/cassandra/ha_cassandra.cc
index f0ad2e39081..ff758a57872 100644
--- a/storage/cassandra/ha_cassandra.cc
+++ b/storage/cassandra/ha_cassandra.cc
@@ -411,7 +411,7 @@ int ha_cassandra::check_field_options(Field **fields)
{
if (dyncol_set || (*field)->type() != MYSQL_TYPE_BLOB)
{
- my_error(ER_WRONG_FIELD_SPEC, MYF(0), (*field)->field_name);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), (*field)->field_name.str);
DBUG_RETURN(HA_WRONG_CREATE_OPTION);
}
dyncol_set= 1;
@@ -1497,14 +1497,14 @@ bool ha_cassandra::setup_field_converters(Field **field_arg, uint n_fields)
for (field= field_arg + 1, i= 1; *field; field++, i++)
{
if ((!dyncol_set || dyncol_field != i) &&
- !strcmp((*field)->field_name, col_name))
+ !strcmp((*field)->field_name.str, col_name))
{
n_mapped++;
ColumnDataConverter **conv= field_converters + (*field)->field_index;
if (!(*conv= map_field_to_validator(*field, col_type)))
{
se->print_error("Failed to map column %s to datatype %s",
- (*field)->field_name, col_type);
+ (*field)->field_name.str, col_type);
my_error(ER_INTERNAL_ERROR, MYF(0), se->error_str());
DBUG_RETURN(true);
}
@@ -1543,7 +1543,7 @@ bool ha_cassandra::setup_field_converters(Field **field_arg, uint n_fields)
DBUG_ASSERT(first_unmapped);
se->print_error("Field `%s` could not be mapped to any field in Cassandra",
- first_unmapped->field_name);
+ first_unmapped->field_name.str);
my_error(ER_INTERNAL_ERROR, MYF(0), se->error_str());
DBUG_RETURN(true);
}
@@ -1552,14 +1552,14 @@ bool ha_cassandra::setup_field_converters(Field **field_arg, uint n_fields)
Setup type conversion for row_key.
*/
se->get_rowkey_type(&col_name, &col_type);
- if (col_name && strcmp(col_name, (*field_arg)->field_name))
+ if (col_name && strcmp(col_name, (*field_arg)->field_name.str))
{
se->print_error("PRIMARY KEY column must match Cassandra's name '%s'",
col_name);
my_error(ER_INTERNAL_ERROR, MYF(0), se->error_str());
DBUG_RETURN(true);
}
- if (!col_name && strcmp("rowkey", (*field_arg)->field_name))
+ if (!col_name && strcmp("rowkey", (*field_arg)->field_name.str))
{
se->print_error("target column family has no key_alias defined, "
"PRIMARY KEY column must be named 'rowkey'");
@@ -1742,14 +1742,14 @@ int ha_cassandra::read_cassandra_columns(bool unpack_pk)
{
uint fieldnr= (*field)->field_index;
if ((!dyncol_set || dyncol_field != fieldnr) &&
- !strcmp((*field)->field_name, cass_name))
+ !strcmp((*field)->field_name.str, cass_name))
{
found= 1;
(*field)->set_notnull();
if (field_converters[fieldnr]->cassandra_to_mariadb(cass_value,
cass_value_len))
{
- print_conversion_error((*field)->field_name, cass_value,
+ print_conversion_error((*field)->field_name.str, cass_value,
cass_value_len);
res=1;
goto err;
@@ -1770,7 +1770,7 @@ int ha_cassandra::read_cassandra_columns(bool unpack_pk)
se->print_error("Unable to convert value for field `%s`"
" from Cassandra's data format. Name"
" length exceed limit of %u: '%s'",
- table->field[dyncol_field]->field_name,
+ table->field[dyncol_field]->field_name.str,
(uint)MAX_NAME_LENGTH, cass_name);
my_error(ER_INTERNAL_ERROR, MYF(0), se->error_str());
res=1;
@@ -1782,7 +1782,7 @@ int ha_cassandra::read_cassandra_columns(bool unpack_pk)
se->print_error("Unable to convert value for field `%s`"
" from Cassandra's data format. Sum of all names"
" length exceed limit of %lu",
- table->field[dyncol_field]->field_name,
+ table->field[dyncol_field]->field_name.str,
cass_name, (uint)MAX_TOTAL_NAME_LENGTH);
my_error(ER_INTERNAL_ERROR, MYF(0), se->error_str());
res=1;
@@ -1841,7 +1841,7 @@ int ha_cassandra::read_cassandra_columns(bool unpack_pk)
se->get_read_rowkey(&cass_value, &cass_value_len);
if (rowkey_converter->cassandra_to_mariadb(cass_value, cass_value_len))
{
- print_conversion_error((*field)->field_name, cass_value, cass_value_len);
+ print_conversion_error((*field)->field_name.str, cass_value, cass_value_len);
res=1;
goto err;
}
@@ -1953,7 +1953,7 @@ int ha_cassandra::write_row(uchar *buf)
if (rowkey_converter->mariadb_to_cassandra(&cass_key, &cass_key_len))
{
my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
- rowkey_converter->field->field_name, insert_lineno);
+ rowkey_converter->field->field_name.str, insert_lineno);
dbug_tmp_restore_column_map(table->read_set, old_map);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
@@ -1987,11 +1987,11 @@ int ha_cassandra::write_row(uchar *buf)
&cass_data_len))
{
my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
- field_converters[i]->field->field_name, insert_lineno);
+ field_converters[i]->field->field_name.str, insert_lineno);
dbug_tmp_restore_column_map(table->read_set, old_map);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
- se->add_insert_column(field_converters[i]->field->field_name, 0,
+ se->add_insert_column(field_converters[i]->field->field_name.str, 0,
cass_data, cass_data_len);
}
}
@@ -2074,7 +2074,7 @@ int ha_cassandra::rnd_init(bool scan)
{
se->clear_read_columns();
for (uint i= 1; i < table->s->fields; i++)
- se->add_read_column(table->field[i]->field_name);
+ se->add_read_column(table->field[i]->field_name.str);
}
se->read_batch_size= THDVAR(table->in_use, rnd_batch_size);
@@ -2171,7 +2171,7 @@ int ha_cassandra::info(uint flag)
}
-void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
+void key_copy(uchar *to_key, const uchar *from_record, KEY *key_info,
uint key_length, bool with_zerofill);
@@ -2355,7 +2355,7 @@ public:
if (idx == obj->table->s->fields)
return NULL;
else
- return obj->table->field[idx++]->field_name;
+ return obj->table->field[idx++]->field_name.str;
}
};
@@ -2386,7 +2386,7 @@ int ha_cassandra::update_row(const uchar *old_data, uchar *new_data)
if (rowkey_converter->mariadb_to_cassandra(&new_key, &new_key_len))
{
my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
- rowkey_converter->field->field_name, insert_lineno);
+ rowkey_converter->field->field_name.str, insert_lineno);
dbug_tmp_restore_column_map(table->read_set, old_map);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
@@ -2449,11 +2449,11 @@ int ha_cassandra::update_row(const uchar *old_data, uchar *new_data)
if (field_converters[i]->mariadb_to_cassandra(&cass_data, &cass_data_len))
{
my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0),
- field_converters[i]->field->field_name, insert_lineno);
+ field_converters[i]->field->field_name.str, insert_lineno);
dbug_tmp_restore_column_map(table->read_set, old_map);
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
- se->add_insert_column(field_converters[i]->field->field_name, 0,
+ se->add_insert_column(field_converters[i]->field->field_name.str, 0,
cass_data, cass_data_len);
}
}
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index a8ff2e739fb..72d6ddda8b1 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -244,7 +244,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
/****************************************************************************/
/* Return str as a zero terminated string. */
/****************************************************************************/
-static char *strz(PGLOBAL g, LEX_STRING &ls)
+static char *strz(PGLOBAL g, LEX_CSTRING &ls)
{
char *str= (char*)PlugSubAlloc(g, NULL, ls.length + 1);
@@ -1242,7 +1242,7 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef)
PTOS options= GetTableOptionStruct();
if (!stricmp(opname, "Connect")) {
- LEX_STRING cnc= (tshp) ? tshp->connect_string
+ LEX_CSTRING cnc= (tshp) ? tshp->connect_string
: table->s->connect_string;
if (cnc.length)
@@ -1422,7 +1422,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
pcf->Flags= 0;
// Now get column information
- pcf->Name= (char*)fp->field_name;
+ pcf->Name= (char*)fp->field_name.str;
if (fop && fop->special) {
pcf->Fieldfmt= (char*)fop->special;
@@ -1619,7 +1619,7 @@ PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
// Get the the key parts info
for (int k= 0; (unsigned)k < kp.user_defined_key_parts; k++) {
- pn= (char*)kp.key_part[k].field->field_name;
+ pn= (char*)kp.key_part[k].field->field_name.str;
name= PlugDup(g, pn);
// Allocate the key part description block
@@ -1735,7 +1735,7 @@ int ha_connect::GetColNameLen(Field *fp)
if (fop && fop->special)
n= strlen(fop->special) + 1;
else
- n= strlen(fp->field_name);
+ n= fp->field_name.length;
return n;
} // end of GetColNameLen
@@ -1747,7 +1747,7 @@ char *ha_connect::GetColName(Field *fp)
{
PFOS fop= GetFieldOptionStruct(fp);
- return (fop && fop->special) ? fop->special : (char*)fp->field_name;
+ return (fop && fop->special) ? fop->special : (char*)fp->field_name.str;
} // end of GetColName
/****************************************************************************/
@@ -1762,7 +1762,7 @@ void ha_connect::AddColName(char *cp, Field *fp)
// The prefix * mark the column as "special"
strcat(strcpy(cp, "*"), strupr(fop->special));
else
- strcpy(cp, (char*)fp->field_name);
+ strcpy(cp, fp->field_name.str);
} // end of AddColName
#endif // 0
@@ -1849,12 +1849,12 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
for (field= table->field; fp= *field; field++) {
if (bitmap_is_set(map, fp->field_index)) {
- n1+= (strlen(fp->field_name) + 1);
+ n1+= (fp->field_name.length + 1);
k1++;
} // endif
if (ump && bitmap_is_set(ump, fp->field_index)) {
- n2+= (strlen(fp->field_name) + 1);
+ n2+= (fp->field_name.length + 1);
k2++;
} // endif
@@ -1865,8 +1865,8 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
for (field= table->field; fp= *field; field++)
if (bitmap_is_set(map, fp->field_index)) {
- strcpy(p, (char*)fp->field_name);
- p+= (strlen(p) + 1);
+ strcpy(p, fp->field_name.str);
+ p+= (fp->field_name.length + 1);
} // endif used field
*p= '\0'; // mark end of list
@@ -1877,7 +1877,7 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
for (field= table->field; fp= *field; field++)
if (bitmap_is_set(ump, fp->field_index)) {
- strcpy(p, (char*)fp->field_name);
+ strcpy(p, fp->field_name.str);
if (part_id && bitmap_is_set(part_id, fp->field_index)) {
// Trying to update a column used for partitioning
@@ -1935,9 +1935,9 @@ bool ha_connect::CheckColumnList(PGLOBAL g)
try {
for (field= table->field; fp= *field; field++)
if (bitmap_is_set(map, fp->field_index)) {
- if (!(colp= tdbp->ColDB(g, (PSZ)fp->field_name, 0))) {
+ if (!(colp= tdbp->ColDB(g, (PSZ)fp->field_name.str, 0))) {
sprintf(g->Message, "Column %s not found in %s",
- fp->field_name, tdbp->GetName());
+ fp->field_name.str, tdbp->GetName());
throw 1;
} // endif colp
@@ -2031,14 +2031,14 @@ int ha_connect::MakeRecord(char *buf)
// This is a used field, fill the buffer with value
for (colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
if ((!mrr || colp->GetKcol()) &&
- !stricmp(colp->GetName(), (char*)fp->field_name))
+ !stricmp(colp->GetName(), fp->field_name.str))
break;
if (!colp) {
if (mrr)
continue;
- htrc("Column %s not found\n", fp->field_name);
+ htrc("Column %s not found\n", fp->field_name.str);
dbug_tmp_restore_column_map(table->write_set, org_bitmap);
DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
} // endif colp
@@ -2094,7 +2094,7 @@ int ha_connect::MakeRecord(char *buf)
sprintf(buf, "Out of range value %.140s for column '%s' at row %ld",
value->GetCharString(val),
- fp->field_name,
+ fp->field_name.str,
thd->get_stmt_da()->current_row_for_warning());
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, buf);
@@ -2125,7 +2125,7 @@ int ha_connect::MakeRecord(char *buf)
/***********************************************************************/
/* Set row values from a MySQL pseudo record. Specific to MySQL. */
/***********************************************************************/
-int ha_connect::ScanRecord(PGLOBAL g, uchar *)
+int ha_connect::ScanRecord(PGLOBAL g, const uchar *)
{
char attr_buffer[1024];
char data_buffer[1024];
@@ -2154,11 +2154,11 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *)
&& tdbp->GetAmType() != TYPE_AM_JDBC) ||
bitmap_is_set(table->write_set, fp->field_index)) {
for (colp= tdbp->GetSetCols(); colp; colp= colp->GetNext())
- if (!stricmp(colp->GetName(), fp->field_name))
+ if (!stricmp(colp->GetName(), fp->field_name.str))
break;
if (!colp) {
- htrc("Column %s not found\n", fp->field_name);
+ htrc("Column %s not found\n", fp->field_name.str);
rc= HA_ERR_WRONG_IN_RECORD;
goto err;
} else
@@ -2268,7 +2268,7 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *)
/* Check change in index column. Specific to MySQL. */
/* Should be elaborated to check for real changes. */
/***********************************************************************/
-int ha_connect::CheckRecord(PGLOBAL g, const uchar *, uchar *newbuf)
+int ha_connect::CheckRecord(PGLOBAL g, const uchar *, const uchar *newbuf)
{
return ScanRecord(g, newbuf);
} // end of dummy CheckRecord
@@ -2350,10 +2350,10 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
if (q) {
qry->Append(q);
- qry->Append((PSZ)fp->field_name);
+ qry->Append((PSZ)fp->field_name.str);
qry->Append(q);
} else
- qry->Append((PSZ)fp->field_name);
+ qry->Append((PSZ)fp->field_name.str);
switch (ranges[i]->flag) {
case HA_READ_KEY_EXACT:
@@ -2612,7 +2612,7 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
return NULL;
if (pField->field->table != table ||
- !(colp[i]= tdbp->ColDB(g, (PSZ)pField->field->field_name, 0)))
+ !(colp[i]= tdbp->ColDB(g, (PSZ)pField->field->field_name.str, 0)))
return NULL; // Column does not belong to this table
// These types are not yet implemented (buggy)
@@ -2630,7 +2630,7 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
if (trace) {
htrc("Field index=%d\n", pField->field->field_index);
- htrc("Field name=%s\n", pField->field->field_name);
+ htrc("Field name=%s\n", pField->field->field_name.str);
} // endif trace
} else {
@@ -2723,7 +2723,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
htrc("Cond type=%d\n", cond->type());
if (cond->type() == COND::COND_ITEM) {
- char *pb0, *pb1, *pb2, *ph0, *ph1, *ph2;
+ char *pb0, *pb1, *pb2, *ph0= 0, *ph1= 0, *ph2= 0;
bool bb = false, bh = false;
Item_cond *cond_item= (Item_cond *)cond;
@@ -2890,7 +2890,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
} else {
bool h;
- fnm = filp->Chk(pField->field->field_name, &h);
+ fnm = filp->Chk(pField->field->field_name.str, &h);
if (h && i && !ishav)
return NULL; // Having should be col VOP arg
@@ -2901,7 +2901,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
if (trace) {
htrc("Field index=%d\n", pField->field->field_index);
- htrc("Field name=%s\n", pField->field->field_name);
+ htrc("Field name=%s\n", pField->field->field_name.str);
htrc("Field type=%d\n", pField->field->type());
htrc("Field_type=%d\n", args[i]->field_type());
} // endif trace
@@ -3468,7 +3468,7 @@ int ha_connect::write_row(uchar *buf)
@see
sql_select.cc, sql_acl.cc, sql_update.cc and sql_insert.cc
*/
-int ha_connect::update_row(const uchar *old_data, uchar *new_data)
+int ha_connect::update_row(const uchar *old_data, const uchar *new_data)
{
int rc= 0;
PGLOBAL& g= xp->g;
@@ -4235,7 +4235,7 @@ int ha_connect::delete_all_rows()
} // end of delete_all_rows
-bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
+bool ha_connect::check_privileges(THD *thd, PTOS options, const char *dbn, bool quick)
{
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
@@ -5445,7 +5445,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} // endif p
} else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
- tab = table_s->table_name.str; // Default value
+ tab = (char *) table_s->table_name.str; // Default value
} // endif tab
@@ -6099,7 +6099,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
TABTYPE type;
TABLE *st= table; // Probably unuseful
THD *thd= ha_thd();
- LEX_STRING cnc = table_arg->s->connect_string;
+ LEX_CSTRING cnc = table_arg->s->connect_string;
#if defined(WITH_PARTITION_STORAGE_ENGINE)
partition_info *part_info= table_arg->part_info;
#endif // WITH_PARTITION_STORAGE_ENGINE
@@ -6335,7 +6335,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (fp->flags & (BLOB_FLAG | ENUM_FLAG | SET_FLAG)) {
sprintf(g->Message, "Unsupported type for column %s",
- fp->field_name);
+ fp->field_name.str);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc= HA_ERR_INTERNAL_ERROR;
DBUG_RETURN(rc);
@@ -6371,11 +6371,11 @@ int ha_connect::create(const char *name, TABLE *table_arg,
case MYSQL_TYPE_STRING:
if (!fp->field_length) {
sprintf(g->Message, "Unsupported 0 length for column %s",
- fp->field_name);
+ fp->field_name.str);
rc= HA_ERR_INTERNAL_ERROR;
my_printf_error(ER_UNKNOWN_ERROR,
"Unsupported 0 length for column %s",
- MYF(0), fp->field_name);
+ MYF(0), fp->field_name.str);
DBUG_RETURN(rc);
} // endif fp
@@ -6390,12 +6390,12 @@ int ha_connect::create(const char *name, TABLE *table_arg,
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
default:
-// fprintf(stderr, "Unsupported type column %s\n", fp->field_name);
+// fprintf(stderr, "Unsupported type column %s\n", fp->field_name.str);
sprintf(g->Message, "Unsupported type for column %s",
- fp->field_name);
+ fp->field_name.str);
rc= HA_ERR_INTERNAL_ERROR;
my_printf_error(ER_UNKNOWN_ERROR, "Unsupported type for column %s",
- MYF(0), fp->field_name);
+ MYF(0), fp->field_name.str);
DBUG_RETURN(rc);
break;
} // endswitch type
@@ -6410,12 +6410,12 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (dbf) {
bool b= false;
- if ((b= strlen(fp->field_name) > 10))
+ if ((b= fp->field_name.length > 10))
sprintf(g->Message, "DBF: Column name '%s' is too long (max=10)",
- fp->field_name);
+ fp->field_name.str);
else if ((b= fp->field_length > 255))
sprintf(g->Message, "DBF: Column length too big for '%s' (max=255)",
- fp->field_name);
+ fp->field_name.str);
if (b) {
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 9d71aaa5433..1d2db91bc6f 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -207,8 +207,8 @@ public:
bool IsOpened(void);
int CloseTable(PGLOBAL g);
int MakeRecord(char *buf);
- int ScanRecord(PGLOBAL g, uchar *buf);
- int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
+ int ScanRecord(PGLOBAL g, const uchar *buf);
+ int CheckRecord(PGLOBAL g, const uchar *oldbuf, const uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const key_range *kr= NULL);
bool IsIndexed(Field *fp);
bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
@@ -389,7 +389,7 @@ PFIL CondFilter(PGLOBAL g, Item *cond);
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
- int update_row(const uchar *old_data, uchar *new_data);
+ int update_row(const uchar *old_data, const uchar *new_data);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
@@ -504,7 +504,7 @@ private:
DsMrr_impl ds_mrr;
protected:
- bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false);
+ bool check_privileges(THD *thd, PTOS options, const char *dbn, bool quick=false);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
char *GetDBfromName(const char *name);
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index cf720bfda12..b44e9c1309b 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -1520,7 +1520,8 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
if (args->arg_count > (unsigned)i) {
int j = 0, n = args->attribute_lengths[i];
my_bool b; // true if attribute is zero terminated
- PSZ p, s = args->attributes[i];
+ PSZ p;
+ const char *s = args->attributes[i];
if (s && *s && (n || *s == '\'')) {
if ((b = (!n || !s[n])))
@@ -1539,7 +1540,7 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
} // endif *s
if (n < 1)
- return "Key";
+ return (char*) "Key";
if (!b) {
p = (PSZ)PlugSubAlloc(g, NULL, n + 1);
@@ -1550,10 +1551,10 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
} // endif s
- return s;
+ return (char*) s;
} // endif count
- return "Key";
+ return (char*) "Key";
} // end of MakeKey
/*********************************************************************************/
diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp
index 8f6e610dfc2..1d76e0417fa 100644
--- a/storage/connect/tabext.cpp
+++ b/storage/connect/tabext.cpp
@@ -294,7 +294,7 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
if (Srcdef) {
if ((catp = strstr(Srcdef, "%s"))) {
- char *fil1, *fil2;
+ char *fil1= 0, *fil2;
PCSZ ph = ((EXTDEF*)To_Def)->Phpos;
if (!ph)
diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp
index 0bf3f6beb43..9570fbf882a 100644
--- a/storage/connect/tabtbl.cpp
+++ b/storage/connect/tabtbl.cpp
@@ -228,7 +228,7 @@ bool TDBTBL::InitTableList(PGLOBAL g)
{
int n;
uint sln;
- char *scs;
+ const char *scs;
PTABLE tp, tabp;
PCOL colp;
PTBLDEF tdp = (PTBLDEF)To_Def;
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index 574cef28ea3..158cf744a4a 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -182,7 +182,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
// Get column name
crp = qrp->Colresp; // Column_Name
- colname = (char *)fp->field_name;
+ colname = (char *)fp->field_name.str;
crp->Kdata->SetValue(colname, i);
chset = (char *)fp->charset()->name;
@@ -263,7 +263,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
crp = crp->Next; // Remark
// For Valgrind
- if (fp->comment.length > 0 && (fld = fp->comment.str))
+ if (fp->comment.length > 0 && (fld = (char*) fp->comment.str))
crp->Kdata->SetValue(fld, fp->comment.length, i);
else
crp->Kdata->Reset(i);
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 7e0c61ff634..f00fe0e201f 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -522,7 +522,7 @@ ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
Encode a buffer into the quoted format.
*/
-int ha_tina::encode_quote(uchar *buf)
+int ha_tina::encode_quote(const uchar *buf)
{
char attribute_buffer[1024];
String attribute(attribute_buffer, sizeof(attribute_buffer),
@@ -1066,7 +1066,7 @@ int ha_tina::open_update_temp_file_if_needed()
This will be called in a table scan right before the previous ::rnd_next()
call.
*/
-int ha_tina::update_row(const uchar * old_data, uchar * new_data)
+int ha_tina::update_row(const uchar * old_data, const uchar * new_data)
{
int size;
int rc= -1;
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index 127c6053a53..c75a64faa52 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -137,7 +137,7 @@ public:
int open(const char *name, int mode, uint open_options);
int close(void);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int rnd_init(bool scan=1);
int rnd_next(uchar *buf);
@@ -173,7 +173,7 @@ public:
void update_status();
/* The following methods were added just for TINA */
- int encode_quote(uchar *buf);
+ int encode_quote(const uchar *buf);
int find_current_row(uchar *buf);
int chain_append();
};
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index 3a5b269e79f..657f5cb9d01 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -431,7 +431,7 @@ int ha_example::write_row(uchar *buf)
@see
sql_select.cc, sql_acl.cc, sql_update.cc and sql_insert.cc
*/
-int ha_example::update_row(const uchar *old_data, uchar *new_data)
+int ha_example::update_row(const uchar *old_data, const uchar *new_data)
{
DBUG_ENTER("ha_example::update_row");
@@ -896,7 +896,7 @@ int ha_example::create(const char *name, TABLE *table_arg,
ha_field_option_struct *field_options= (*field)->option_struct;
DBUG_ASSERT(field_options);
DBUG_PRINT("info", ("field: %s complex: '%-.64s'",
- (*field)->field_name,
+ (*field)->field_name.str,
(field_options->complex_param_to_parse_it_in_engine ?
field_options->complex_param_to_parse_it_in_engine :
"<NULL>")));
@@ -975,7 +975,7 @@ ha_example::check_if_supported_inplace_alter(TABLE* altered_table,
{
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: Field %`s COMPLEX '%s' -> '%s'",
- table->s->field[i]->field_name,
+ table->s->field[i]->field_name.str,
f_old->complex_param_to_parse_it_in_engine,
f_new->complex_param_to_parse_it_in_engine);
}
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index 2d3d0c81ed9..3a9654bbb7b 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -186,7 +186,7 @@ public:
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
- int update_row(const uchar *old_data, uchar *new_data);
+ int update_row(const uchar *old_data, const uchar *new_data);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index ef48665d92a..a3121f56d7c 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -420,7 +420,7 @@ static int federated_rollback(handlerton *hton, THD *thd, bool all);
/* Federated storage engine handlerton */
-static handler *federated_create_handler(handlerton *hton,
+static handler *federated_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root)
{
@@ -754,9 +754,9 @@ static int parse_url(MEM_ROOT *mem_root, FEDERATED_SHARE *share, TABLE *table,
share->table_name++;
share->table_name_length= (uint) strlen(share->table_name);
- DBUG_PRINT("info",
+ DBUG_PRINT("info",
("internal format, parsed table_name share->connection_string \
- %s share->table_name %s",
+ %s share->table_name %s",
share->connection_string, share->table_name));
/*
@@ -778,9 +778,9 @@ static int parse_url(MEM_ROOT *mem_root, FEDERATED_SHARE *share, TABLE *table,
*/
share->table_name= strmake_root(mem_root, table->s->table_name.str,
(share->table_name_length= table->s->table_name.length));
- DBUG_PRINT("info",
+ DBUG_PRINT("info",
("internal format, default table_name share->connection_string \
- %s share->table_name %s",
+ %s share->table_name %s",
share->connection_string, share->table_name));
}
@@ -972,8 +972,8 @@ uint ha_federated::convert_row_to_internal_format(uchar *record,
static bool emit_key_part_name(String *to, KEY_PART_INFO *part)
{
DBUG_ENTER("emit_key_part_name");
- if (append_ident(to, part->field->field_name,
- strlen(part->field->field_name), ident_quote_char))
+ if (append_ident(to, part->field->field_name.str,
+ part->field->field_name.length, ident_quote_char))
DBUG_RETURN(1); // Out of memory
DBUG_RETURN(0);
}
@@ -1235,7 +1235,7 @@ read_range_first: start_key 3 end_key 3
Summary:
-* If the start key flag is 0 the max key flag shouldn't even be set,
+* If the start key flag is 0 the max key flag shouldn't even be set,
and if it is, the query produced would be invalid.
* Multipart keys, even if containing some or all numeric columns,
are treated the same as non-numeric keys
@@ -1534,8 +1534,8 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
query.append(STRING_WITH_LEN("SELECT "));
for (field= table->field; *field; field++)
{
- append_ident(&query, (*field)->field_name,
- strlen((*field)->field_name), ident_quote_char);
+ append_ident(&query, (*field)->field_name.str,
+ (*field)->field_name.length, ident_quote_char);
query.append(STRING_WITH_LEN(", "));
}
/* chops off trailing comma */
@@ -1543,7 +1543,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
query.append(STRING_WITH_LEN(" FROM "));
- append_ident(&query, tmp_share.table_name,
+ append_ident(&query, tmp_share.table_name,
tmp_share.table_name_length, ident_quote_char);
if (!(share= (FEDERATED_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
@@ -1763,7 +1763,7 @@ bool ha_federated::append_stmt_insert(String *query)
insert_string.append(STRING_WITH_LEN("INSERT IGNORE INTO "));
else
insert_string.append(STRING_WITH_LEN("INSERT INTO "));
- append_ident(&insert_string, share->table_name, share->table_name_length,
+ append_ident(&insert_string, share->table_name, share->table_name_length,
ident_quote_char);
tmp_length= insert_string.length();
insert_string.append(STRING_WITH_LEN(" ("));
@@ -1777,8 +1777,8 @@ bool ha_federated::append_stmt_insert(String *query)
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
/* append the field name */
- append_ident(&insert_string, (*field)->field_name,
- strlen((*field)->field_name), ident_quote_char);
+ append_ident(&insert_string, (*field)->field_name.str,
+ (*field)->field_name.length, ident_quote_char);
/* append commas between both fields and fieldnames */
/*
@@ -1927,11 +1927,11 @@ int ha_federated::write_row(uchar *buf)
if (bulk_insert.length == 0)
{
char insert_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- String insert_string(insert_buffer, sizeof(insert_buffer),
+ String insert_string(insert_buffer, sizeof(insert_buffer),
&my_charset_bin);
insert_string.length(0);
append_stmt_insert(&insert_string);
- dynstr_append_mem(&bulk_insert, insert_string.ptr(),
+ dynstr_append_mem(&bulk_insert, insert_string.ptr(),
insert_string.length());
}
else
@@ -2069,7 +2069,7 @@ int ha_federated::optimize(THD* thd, HA_CHECK_OPT* check_opt)
query.set_charset(system_charset_info);
query.append(STRING_WITH_LEN("OPTIMIZE TABLE "));
- append_ident(&query, share->table_name, share->table_name_length,
+ append_ident(&query, share->table_name, share->table_name_length,
ident_quote_char);
if (real_query(query.ptr(), query.length()))
@@ -2091,7 +2091,7 @@ int ha_federated::repair(THD* thd, HA_CHECK_OPT* check_opt)
query.set_charset(system_charset_info);
query.append(STRING_WITH_LEN("REPAIR TABLE "));
- append_ident(&query, share->table_name, share->table_name_length,
+ append_ident(&query, share->table_name, share->table_name_length,
ident_quote_char);
if (check_opt->flags & T_QUICK)
query.append(STRING_WITH_LEN(" QUICK"));
@@ -2126,7 +2126,7 @@ int ha_federated::repair(THD* thd, HA_CHECK_OPT* check_opt)
Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
*/
-int ha_federated::update_row(const uchar *old_data, uchar *new_data)
+int ha_federated::update_row(const uchar *old_data, const uchar *new_data)
{
/*
This used to control how the query was built. If there was a
@@ -2191,8 +2191,8 @@ int ha_federated::update_row(const uchar *old_data, uchar *new_data)
{
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
- size_t field_name_length= strlen((*field)->field_name);
- append_ident(&update_string, (*field)->field_name, field_name_length,
+ append_ident(&update_string, (*field)->field_name.str,
+ (*field)->field_name.length,
ident_quote_char);
update_string.append(STRING_WITH_LEN(" = "));
@@ -2217,8 +2217,8 @@ int ha_federated::update_row(const uchar *old_data, uchar *new_data)
if (bitmap_is_set(table->read_set, (*field)->field_index))
{
- size_t field_name_length= strlen((*field)->field_name);
- append_ident(&where_string, (*field)->field_name, field_name_length,
+ append_ident(&where_string, (*field)->field_name.str,
+ (*field)->field_name.length,
ident_quote_char);
if (field_in_record_is_null(table, *field, (char*) old_data))
where_string.append(STRING_WITH_LEN(" IS NULL "));
@@ -2300,8 +2300,8 @@ int ha_federated::delete_row(const uchar *buf)
found++;
if (bitmap_is_set(table->read_set, cur_field->field_index))
{
- append_ident(&delete_string, (*field)->field_name,
- strlen((*field)->field_name), ident_quote_char);
+ append_ident(&delete_string, (*field)->field_name.str,
+ (*field)->field_name.length, ident_quote_char);
data_string.length(0);
if (cur_field->is_null())
{
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index a23375cbe58..e264258a63a 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -210,7 +210,7 @@ public:
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();
int write_row(uchar *buf);
- int update_row(const uchar *old_data, uchar *new_data);
+ int update_row(const uchar *old_data, const uchar *new_data);
int delete_row(const uchar *buf);
int index_init(uint keynr, bool sorted);
ha_rows estimate_rows_upper_bound();
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index e3506e1a4df..17f228c1209 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -892,8 +892,8 @@ uint ha_federatedx::convert_row_to_internal_format(uchar *record,
static bool emit_key_part_name(String *to, KEY_PART_INFO *part)
{
DBUG_ENTER("emit_key_part_name");
- if (append_ident(to, part->field->field_name,
- strlen(part->field->field_name), ident_quote_char))
+ if (append_ident(to, part->field->field_name.str,
+ part->field->field_name.length, ident_quote_char))
DBUG_RETURN(1); // Out of memory
DBUG_RETURN(0);
}
@@ -1595,8 +1595,8 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
query.append(STRING_WITH_LEN("SELECT "));
for (field= table->field; *field; field++)
{
- append_ident(&query, (*field)->field_name,
- strlen((*field)->field_name), ident_quote_char);
+ append_ident(&query, (*field)->field_name.str,
+ (*field)->field_name.length, ident_quote_char);
query.append(STRING_WITH_LEN(", "));
}
/* chops off trailing comma */
@@ -1604,7 +1604,7 @@ static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table)
query.append(STRING_WITH_LEN(" FROM "));
- append_ident(&query, tmp_share.table_name,
+ append_ident(&query, tmp_share.table_name,
tmp_share.table_name_length, ident_quote_char);
if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
@@ -1900,7 +1900,7 @@ bool ha_federatedx::append_stmt_insert(String *query)
insert_string.append(STRING_WITH_LEN("INSERT IGNORE INTO "));
else
insert_string.append(STRING_WITH_LEN("INSERT INTO "));
- append_ident(&insert_string, share->table_name, share->table_name_length,
+ append_ident(&insert_string, share->table_name, share->table_name_length,
ident_quote_char);
tmp_length= insert_string.length();
insert_string.append(STRING_WITH_LEN(" ("));
@@ -1914,8 +1914,8 @@ bool ha_federatedx::append_stmt_insert(String *query)
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
/* append the field name */
- append_ident(&insert_string, (*field)->field_name,
- strlen((*field)->field_name), ident_quote_char);
+ append_ident(&insert_string, (*field)->field_name.str,
+ (*field)->field_name.length, ident_quote_char);
/* append commas between both fields and fieldnames */
/*
@@ -2212,7 +2212,7 @@ int ha_federatedx::optimize(THD* thd, HA_CHECK_OPT* check_opt)
query.set_charset(system_charset_info);
query.append(STRING_WITH_LEN("OPTIMIZE TABLE "));
- append_ident(&query, share->table_name, share->table_name_length,
+ append_ident(&query, share->table_name, share->table_name_length,
ident_quote_char);
DBUG_ASSERT(txn == get_txn(thd));
@@ -2238,7 +2238,7 @@ int ha_federatedx::repair(THD* thd, HA_CHECK_OPT* check_opt)
query.set_charset(system_charset_info);
query.append(STRING_WITH_LEN("REPAIR TABLE "));
- append_ident(&query, share->table_name, share->table_name_length,
+ append_ident(&query, share->table_name, share->table_name_length,
ident_quote_char);
if (check_opt->flags & T_QUICK)
query.append(STRING_WITH_LEN(" QUICK"));
@@ -2276,7 +2276,7 @@ int ha_federatedx::repair(THD* thd, HA_CHECK_OPT* check_opt)
Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc.
*/
-int ha_federatedx::update_row(const uchar *old_data, uchar *new_data)
+int ha_federatedx::update_row(const uchar *old_data, const uchar *new_data)
{
/*
This used to control how the query was built. If there was a
@@ -2342,8 +2342,8 @@ int ha_federatedx::update_row(const uchar *old_data, uchar *new_data)
{
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
- uint field_name_length= strlen((*field)->field_name);
- append_ident(&update_string, (*field)->field_name, field_name_length,
+ append_ident(&update_string, (*field)->field_name.str,
+ (*field)->field_name.length,
ident_quote_char);
update_string.append(STRING_WITH_LEN(" = "));
@@ -2368,8 +2368,8 @@ int ha_federatedx::update_row(const uchar *old_data, uchar *new_data)
if (bitmap_is_set(table->read_set, (*field)->field_index))
{
- uint field_name_length= strlen((*field)->field_name);
- append_ident(&where_string, (*field)->field_name, field_name_length,
+ append_ident(&where_string, (*field)->field_name.str,
+ (*field)->field_name.length,
ident_quote_char);
if (field_in_record_is_null(table, *field, (char*) old_data))
where_string.append(STRING_WITH_LEN(" IS NULL "));
@@ -2455,8 +2455,8 @@ int ha_federatedx::delete_row(const uchar *buf)
found++;
if (bitmap_is_set(table->read_set, cur_field->field_index))
{
- append_ident(&delete_string, (*field)->field_name,
- strlen((*field)->field_name), ident_quote_char);
+ append_ident(&delete_string, (*field)->field_name.str,
+ (*field)->field_name.length, ident_quote_char);
data_string.length(0);
if (cur_field->is_null())
{
diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h
index f8531014ee4..3345bbc2180 100644
--- a/storage/federatedx/ha_federatedx.h
+++ b/storage/federatedx/ha_federatedx.h
@@ -394,7 +394,7 @@ public:
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();
int write_row(uchar *buf);
- int update_row(const uchar *old_data, uchar *new_data);
+ int update_row(const uchar *old_data, const uchar *new_data);
int delete_row(const uchar *buf);
int index_init(uint keynr, bool sorted);
ha_rows estimate_rows_upper_bound();
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index 970c503497f..ef6530e98e1 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -251,7 +251,7 @@ int ha_heap::write_row(uchar * buf)
return res;
}
-int ha_heap::update_row(const uchar * old_data, uchar * new_data)
+int ha_heap::update_row(const uchar * old_data, const uchar * new_data)
{
int res;
res= heap_update(file,old_data,new_data);
@@ -781,6 +781,54 @@ bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_YES;
}
+
+/**
+ Find record by unique index (used in temporary tables with the index)
+
+ @param record (IN|OUT) the record to find
+ @param unique_idx (IN) number of index (for this engine)
+
+ @note It is like hp_search but uses function for raw where hp_search
+ uses functions for index.
+
+ @retval 0 OK
+ @retval 1 Not found
+ @retval -1 Error
+*/
+
+int ha_heap::find_unique_row(uchar *record, uint unique_idx)
+{
+ DBUG_ENTER("ha_heap::find_unique_row");
+ HP_SHARE *share= file->s;
+ DBUG_ASSERT(inited==NONE);
+ HP_KEYDEF *keyinfo= share->keydef + unique_idx;
+ DBUG_ASSERT(keyinfo->algorithm == HA_KEY_ALG_HASH);
+ DBUG_ASSERT(keyinfo->flag & HA_NOSAME);
+ if (!share->records)
+ DBUG_RETURN(1); // not found
+ HASH_INFO *pos= hp_find_hash(&keyinfo->block,
+ hp_mask(hp_rec_hashnr(keyinfo, record),
+ share->blength, share->records));
+ do
+ {
+ if (!hp_rec_key_cmp(keyinfo, pos->ptr_to_rec, record))
+ {
+ file->current_hash_ptr= pos;
+ file->current_ptr= pos->ptr_to_rec;
+ file->update = HA_STATE_AKTIV;
+ /*
+ We compare it only by record in the index, so better to read all
+ records.
+ */
+ memcpy(record, file->current_ptr, (size_t) share->reclength);
+
+ DBUG_RETURN(0); // found and position set
+ }
+ }
+ while ((pos= pos->next_key));
+ DBUG_RETURN(1); // not found
+}
+
struct st_mysql_storage_engine heap_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index 503d3b896ac..e17c18c8b14 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -71,7 +71,7 @@ public:
int close(void);
void set_keys_for_scanning(void);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong nb_desired_values,
@@ -115,6 +115,7 @@ public:
return memcmp(ref1, ref2, sizeof(HEAP_PTR));
}
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
+ int find_unique_row(uchar *record, uint unique_idx);
private:
void update_key_stats();
};
diff --git a/storage/heap/hp_block.c b/storage/heap/hp_block.c
index aa5343a0717..6ecab0d08c4 100644
--- a/storage/heap/hp_block.c
+++ b/storage/heap/hp_block.c
@@ -71,9 +71,9 @@ int hp_get_new_block(HP_SHARE *info, HP_BLOCK *block, size_t *alloc_length)
lower levels.
For example, for level 0, we allocate data for X rows.
- When level 0 is full, we allocate data for HPTRS_IN_NODE + X rows.
+ When level 0 is full, we allocate data for HP_PTRS_IN_NOD + X rows.
Next time we allocate data for X rows.
- When level 1 is full, we allocate data for HPTRS_IN_NODE at level 2 and 1
+ When level 1 is full, we allocate data for HP_PTRS_IN_NOD at level 2 and 1
+ X rows at level 0.
*/
*alloc_length= (sizeof(HP_PTRS) * ((i == block->levels) ? i : i - 1) +
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 24971cfebd4..2dcc5a9b9a9 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1884,7 +1884,7 @@ buf_flush_batch(
buf_pool_mutex_enter(buf_pool);
- ulint count = 0;
+ ulint count __attribute__((unused))= 0;
/* Note: The buffer pool mutex is released and reacquired within
the flush functions. */
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index f54428b4fe6..943a37ef4e0 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -2498,6 +2498,7 @@ dict_index_add_to_cache_w_vcol(
ut_d(mem_heap_validate(index->heap));
ut_a(!dict_index_is_clust(index)
|| UT_LIST_GET_LEN(table->indexes) == 0);
+ ut_ad(dict_index_is_clust(index) || !table->no_rollback());
if (!dict_index_find_cols(table, index, add_v)) {
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 3dc95b1956a..55d84bf17df 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -1163,11 +1163,6 @@ dict_sys_tables_type_valid(ulint type, bool not_redundant)
return(false);
}
- /* ATOMIC_WRITES cannot be 3; it is the 10.3 NO_ROLLBACK flag. */
- if (!(~type & DICT_TF_MASK_ATOMIC_WRITES)) {
- return(false);
- }
-
return(dict_tf_is_valid_not_redundant(type));
}
@@ -1188,7 +1183,8 @@ dict_sys_tables_type_to_tf(ulint type, bool not_redundant)
| DICT_TF_MASK_ATOMIC_BLOBS
| DICT_TF_MASK_DATA_DIR
| DICT_TF_MASK_PAGE_COMPRESSION
- | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL);
+ | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL
+ | DICT_TF_MASK_NO_ROLLBACK);
ut_ad(dict_tf_is_valid(flags));
return(flags);
@@ -1240,7 +1236,8 @@ dict_sys_tables_rec_read(
MariaDB 10.2.2 introduced the SHARED_SPACE flag from MySQL 5.7,
shifting the flags PAGE_COMPRESSION, PAGE_COMPRESSION_LEVEL,
- ATOMIC_WRITES by one bit. The SHARED_SPACE flag would always
+ ATOMIC_WRITES (repurposed to NO_ROLLBACK in 10.3.1) by one bit.
+ The SHARED_SPACE flag would always
be written as 0 by MariaDB, because MariaDB does not support
CREATE TABLESPACE or CREATE TABLE...TABLESPACE for InnoDB.
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 68b69e94681..9e088571f10 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3057,7 +3057,8 @@ innobase_copy_frm_flags_from_create_info(
ibool ps_on;
ibool ps_off;
- if (dict_table_is_temporary(innodb_table)) {
+ if (dict_table_is_temporary(innodb_table)
+ || innodb_table->no_rollback()) {
/* Temp tables do not use persistent stats. */
ps_on = FALSE;
ps_off = TRUE;
@@ -3143,6 +3144,7 @@ ha_innobase::ha_innobase(
*/
| HA_CAN_EXPORT
| HA_CAN_RTREEKEYS
+ | HA_CAN_TABLES_WITHOUT_ROLLBACK
| HA_CONCURRENT_OPTIMIZE
| (srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0)
),
@@ -3317,7 +3319,7 @@ innobase_query_caching_of_table_permitted(
THD* thd, /*!< in: thd of the user who is trying to
store a result to the query cache or
retrieve it */
- char* full_name, /*!< in: normalized path to the table */
+ const char* full_name, /*!< in: normalized path to the table */
uint full_name_len, /*!< in: length of the normalized path
to the table */
ulonglong *unused) /*!< unused for this engine */
@@ -6143,7 +6145,7 @@ innobase_build_v_templ(
name = dict_table_get_v_col_name(ib_table, z);
}
- ut_ad(!ut_strcmp(name, field->field_name));
+ ut_ad(!ut_strcmp(name, field->field_name.str));
#endif
const dict_v_col_t* vcol;
@@ -6178,7 +6180,7 @@ innobase_build_v_templ(
const char* name = dict_table_get_col_name(
ib_table, j);
- ut_ad(!ut_strcmp(name, field->field_name));
+ ut_ad(!ut_strcmp(name, field->field_name.str));
#endif
s_templ->vtempl[j] = static_cast<
@@ -7861,7 +7863,7 @@ build_template_field(
ib::info() << "MySQL table "
<< table->s->table_name.str
<< " field " << j << " name "
- << table->field[j]->field_name;
+ << table->field[j]->field_name.str;
}
ib::error() << "Clustered record field for column " << i
@@ -7988,10 +7990,11 @@ ha_innobase::build_template(
ibool fetch_primary_key_cols = FALSE;
ulint i;
- if (m_prebuilt->select_lock_type == LOCK_X) {
+ if (m_prebuilt->select_lock_type == LOCK_X || m_prebuilt->table->no_rollback()) {
/* We always retrieve the whole clustered index record if we
use exclusive row level locks, for example, if the read is
- done in an UPDATE statement. */
+ done in an UPDATE statement or if we are using a no rollback
+ table */
whole_row = true;
} else if (!whole_row) {
@@ -8871,7 +8874,7 @@ dberr_t
calc_row_difference(
upd_t* uvect,
const uchar* old_row,
- uchar* new_row,
+ const uchar* new_row,
TABLE* table,
uchar* upd_buff,
ulint buff_len,
@@ -8976,7 +8979,7 @@ calc_row_difference(
if (field_mysql_type == MYSQL_TYPE_LONGLONG
&& prebuilt->table->fts
&& innobase_strcasecmp(
- field->field_name, FTS_DOC_ID_COL_NAME) == 0) {
+ field->field_name.str, FTS_DOC_ID_COL_NAME) == 0) {
doc_id = (doc_id_t) mach_read_from_n_little_endian(
n_ptr, 8);
if (doc_id == 0) {
@@ -9366,7 +9369,7 @@ if its index columns are updated!
int
ha_innobase::update_row(
const uchar* old_row,
- uchar* new_row)
+ const uchar* new_row)
{
int err;
@@ -11377,7 +11380,7 @@ create_table_check_doc_id_col(
col_len = field->pack_length();
- if (innobase_strcasecmp(field->field_name,
+ if (innobase_strcasecmp(field->field_name.str,
FTS_DOC_ID_COL_NAME) == 0) {
/* Note the name is case sensitive due to
@@ -11385,7 +11388,7 @@ create_table_check_doc_id_col(
if (col_type == DATA_INT
&& !field->real_maybe_null()
&& col_len == sizeof(doc_id_t)
- && (strcmp(field->field_name,
+ && (strcmp(field->field_name.str,
FTS_DOC_ID_COL_NAME) == 0)) {
*doc_id_col = i;
} else {
@@ -11397,7 +11400,7 @@ create_table_check_doc_id_col(
" of BIGINT NOT NULL type, and named"
" in all capitalized characters");
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
*doc_id_col = ULINT_UNDEFINED;
}
@@ -11468,7 +11471,7 @@ innodb_base_col_setup(
for (z = 0; z < table->n_cols; z++) {
const char* name = dict_table_get_col_name(table, z);
if (!innobase_strcasecmp(name,
- base_field->field_name)) {
+ base_field->field_name.str)) {
break;
}
}
@@ -11509,7 +11512,7 @@ innodb_base_col_setup_for_stored(
const char* name = dict_table_get_col_name(
table, z);
if (!innobase_strcasecmp(
- name, base_field->field_name)) {
+ name, base_field->field_name.str)) {
break;
}
}
@@ -11653,7 +11656,7 @@ create_table_info_t::create_table_def()
" column type and try to re-create"
" the table with an appropriate"
" column type.",
- table->name.m_name, field->field_name);
+ table->name.m_name, field->field_name.str);
goto err_col;
}
@@ -11712,9 +11715,9 @@ create_table_info_t::create_table_def()
/* First check whether the column to be added has a
system reserved name. */
- if (dict_col_name_is_reserved(field->field_name)){
+ if (dict_col_name_is_reserved(field->field_name.str)){
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
err_col:
dict_mem_table_free(table);
mem_heap_free(heap);
@@ -11726,7 +11729,7 @@ err_col:
if (!is_virtual) {
dict_mem_table_add_col(table, heap,
- field->field_name, col_type,
+ field->field_name.str, col_type,
dtype_form_prtype(
(ulint) field->type()
| nulls_allowed | unsigned_type
@@ -11735,7 +11738,7 @@ err_col:
col_len);
} else {
dict_mem_table_add_v_col(table, heap,
- field->field_name, col_type,
+ field->field_name.str, col_type,
dtype_form_prtype(
(ulint) field->type()
| nulls_allowed | unsigned_type
@@ -11917,7 +11920,7 @@ create_index(
}
dict_mem_index_add_field(
- index, key_part->field->field_name, 0);
+ index, key_part->field->field_name.str, 0);
}
DBUG_RETURN(convert_error_code_to_mysql(
@@ -11969,7 +11972,7 @@ create_index(
if (field == NULL)
ut_error;
- const char* field_name = key_part->field->field_name;
+ const char* field_name = key_part->field->field_name.str;
col_type = get_innobase_type_from_mysql_type(
&is_unsigned, key_part->field);
@@ -11995,7 +11998,7 @@ create_index(
" inappropriate data type. Table"
" name %s, column name %s.",
table_name,
- key_part->field->field_name);
+ key_part->field->field_name.str);
prefix_len = 0;
}
@@ -12627,7 +12630,7 @@ create_table_info_t::innobase_table_flags()
/* Do a pre-check on FTS DOC ID index */
if (!(key->flags & HA_NOSAME)
|| strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
- || strcmp(key->key_part[0].field->field_name,
+ || strcmp(key->key_part[0].field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
fts_doc_id_index_bad = key->name;
}
@@ -12808,6 +12811,10 @@ index_bad:
default_compression_level : static_cast<ulint>(options->page_compression_level),
0);
+ if (m_form->s->table_type == TABLE_TYPE_SEQUENCE) {
+ m_flags |= DICT_TF_MASK_NO_ROLLBACK;
+ }
+
/* Set the flags2 when create table or alter tables */
m_flags2 |= DICT_TF2_FTS_AUX_HEX_NAME;
DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
@@ -13432,6 +13439,10 @@ ha_innobase::create(
trx_t* trx;
DBUG_ENTER("ha_innobase::create");
+ DBUG_ASSERT(form->s == table_share);
+ DBUG_ASSERT(table_share->table_type == TABLE_TYPE_SEQUENCE
+ || table_share->table_type == TABLE_TYPE_NORMAL);
+
create_table_info_t info(ha_thd(),
form,
create_info,
@@ -15568,8 +15579,8 @@ get_foreign_key_info(
char tmp_buff[NAME_LEN+1];
char name_buff[NAME_LEN+1];
const char* ptr;
- LEX_STRING* referenced_key_name;
- LEX_STRING* name = NULL;
+ LEX_CSTRING* referenced_key_name;
+ LEX_CSTRING* name = NULL;
ptr = dict_remove_db_name(foreign->id);
f_key_info.foreign_id = thd_make_lex_string(
@@ -16289,24 +16300,23 @@ ha_innobase::external_lock(
}
/* Check for UPDATEs in read-only mode. */
- if (srv_read_only_mode
- && (thd_sql_command(thd) == SQLCOM_UPDATE
- || thd_sql_command(thd) == SQLCOM_INSERT
- || thd_sql_command(thd) == SQLCOM_REPLACE
- || thd_sql_command(thd) == SQLCOM_DROP_TABLE
- || thd_sql_command(thd) == SQLCOM_ALTER_TABLE
- || thd_sql_command(thd) == SQLCOM_OPTIMIZE
- || (thd_sql_command(thd) == SQLCOM_CREATE_TABLE
- && lock_type == F_WRLCK)
- || thd_sql_command(thd) == SQLCOM_CREATE_INDEX
- || thd_sql_command(thd) == SQLCOM_DROP_INDEX
- || thd_sql_command(thd) == SQLCOM_DELETE)) {
-
- if (thd_sql_command(thd) == SQLCOM_CREATE_TABLE) {
- ib_senderrf(thd, IB_LOG_LEVEL_WARN,
- ER_READ_ONLY_MODE);
- DBUG_RETURN(HA_ERR_TABLE_READONLY);
- } else {
+ if (srv_read_only_mode) {
+ switch (thd_sql_command(thd)) {
+ case SQLCOM_CREATE_TABLE:
+ if (lock_type != F_WRLCK) {
+ break;
+ }
+ case SQLCOM_UPDATE:
+ case SQLCOM_INSERT:
+ case SQLCOM_REPLACE:
+ case SQLCOM_DROP_TABLE:
+ case SQLCOM_ALTER_TABLE:
+ case SQLCOM_OPTIMIZE:
+ case SQLCOM_CREATE_INDEX:
+ case SQLCOM_DROP_INDEX:
+ case SQLCOM_CREATE_SEQUENCE:
+ case SQLCOM_DROP_SEQUENCE:
+ case SQLCOM_DELETE:
ib_senderrf(thd, IB_LOG_LEVEL_WARN,
ER_READ_ONLY_MODE);
DBUG_RETURN(HA_ERR_TABLE_READONLY);
@@ -17166,6 +17176,8 @@ ha_innobase::store_lock(
&& lock_type <= TL_WRITE))
|| sql_command == SQLCOM_CREATE_INDEX
|| sql_command == SQLCOM_DROP_INDEX
+ || sql_command == SQLCOM_CREATE_SEQUENCE
+ || sql_command == SQLCOM_DROP_SEQUENCE
|| sql_command == SQLCOM_DELETE)) {
ib_senderrf(trx->mysql_thd,
@@ -17195,7 +17207,8 @@ ha_innobase::store_lock(
}
/* Check for DROP TABLE */
- } else if (sql_command == SQLCOM_DROP_TABLE) {
+ } else if (sql_command == SQLCOM_DROP_TABLE ||
+ sql_command == SQLCOM_DROP_SEQUENCE) {
/* MySQL calls this function in DROP TABLE though this table
handle may belong to another thd that is running a query. Let
@@ -17230,7 +17243,8 @@ ha_innobase::store_lock(
/* Use consistent read for checksum table */
if (sql_command == SQLCOM_CHECKSUM
- || (sql_command == SQLCOM_ANALYZE && lock_type == TL_READ)
+ || sql_command == SQLCOM_CREATE_SEQUENCE
+ || (sql_command == SQLCOM_ANALYZE && lock_type == TL_READ)
|| ((srv_locks_unsafe_for_binlog
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
&& trx->isolation_level != TRX_ISO_SERIALIZABLE
@@ -17239,6 +17253,7 @@ ha_innobase::store_lock(
&& (sql_command == SQLCOM_INSERT_SELECT
|| sql_command == SQLCOM_REPLACE_SELECT
|| sql_command == SQLCOM_UPDATE
+ || sql_command == SQLCOM_CREATE_SEQUENCE
|| sql_command == SQLCOM_CREATE_TABLE))) {
/* If we either have innobase_locks_unsafe_for_binlog
@@ -17734,7 +17749,7 @@ my_bool
ha_innobase::register_query_cache_table(
/*====================================*/
THD* thd, /*!< in: user thread handle */
- char* table_key, /*!< in: normalized path to the
+ const char* table_key, /*!< in: normalized path to the
table */
uint key_length, /*!< in: length of the normalized
path to the table */
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 769d4ae2a59..f9ad2007a5f 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -138,7 +138,7 @@ public:
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
@@ -285,7 +285,7 @@ public:
*/
my_bool register_query_cache_table(
THD* thd,
- char* table_key,
+ const char* table_key,
uint key_length,
qc_engine_callback* call_back,
ulonglong* engine_data);
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 22db204faa2..ceaa07bbd40 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -526,8 +526,8 @@ check_v_col_in_order(
}
if (my_strcasecmp(system_charset_info,
- field->field_name,
- new_field->field_name) != 0) {
+ field->field_name.str,
+ new_field->field_name.str) != 0) {
/* different column */
return(false);
} else {
@@ -842,7 +842,7 @@ ha_innobase::check_if_supported_inplace_alter(
&& innobase_fulltext_exist(altered_table)
&& !my_strcasecmp(
system_charset_info,
- key_part->field->field_name,
+ key_part->field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS);
@@ -939,7 +939,7 @@ ha_innobase::check_if_supported_inplace_alter(
if (!my_strcasecmp(
system_charset_info,
- (*fp)->field_name,
+ (*fp)->field_name.str,
FTS_DOC_ID_COL_NAME)) {
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS);
@@ -1108,7 +1108,7 @@ innobase_init_foreign(
/*==================*/
dict_foreign_t* foreign, /*!< in/out: structure to
initialize */
- char* constraint_name, /*!< in/out: constraint name if
+ const char* constraint_name, /*!< in/out: constraint name if
exists */
dict_table_t* table, /*!< in: foreign table */
dict_index_t* index, /*!< in: foreign key index */
@@ -1316,7 +1316,7 @@ no_match:
}
if (innobase_strcasecmp(col_names[j],
- key_part.field->field_name)) {
+ key_part.field->field_name.str)) {
/* Name mismatch */
goto no_match;
}
@@ -2104,7 +2104,7 @@ name_ok:
}
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
return(ER_WRONG_KEY_COLUMN);
}
@@ -2120,7 +2120,7 @@ name_ok:
}
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
return(ER_WRONG_KEY_COLUMN);
}
}
@@ -2343,20 +2343,20 @@ innobase_fts_check_doc_id_col(
}
if (my_strcasecmp(system_charset_info,
- field->field_name, FTS_DOC_ID_COL_NAME)) {
+ field->field_name.str, FTS_DOC_ID_COL_NAME)) {
continue;
}
- if (strcmp(field->field_name, FTS_DOC_ID_COL_NAME)) {
+ if (strcmp(field->field_name.str, FTS_DOC_ID_COL_NAME)) {
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
} else if (field->type() != MYSQL_TYPE_LONGLONG
|| field->pack_length() != 8
|| field->real_maybe_null()
|| !(field->flags & UNSIGNED_FLAG)
|| innobase_is_v_fld(field)) {
my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0),
- field->field_name);
+ field->field_name.str);
} else {
*fts_doc_col_no = i - *num_v;
}
@@ -2429,7 +2429,7 @@ innobase_fts_check_doc_id_index(
if ((key.flags & HA_NOSAME)
&& key.user_defined_key_parts == 1
&& !strcmp(key.name, FTS_DOC_ID_INDEX_NAME)
- && !strcmp(key.key_part[0].field->field_name,
+ && !strcmp(key.key_part[0].field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
if (fts_doc_col_no) {
*fts_doc_col_no = ULINT_UNDEFINED;
@@ -2508,7 +2508,7 @@ innobase_fts_check_doc_id_index_in_def(
if (!(key->flags & HA_NOSAME)
|| key->user_defined_key_parts != 1
|| strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
- || strcmp(key->key_part[0].field->field_name,
+ || strcmp(key->key_part[0].field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
return(FTS_INCORRECT_DOC_ID_INDEX);
}
@@ -3000,7 +3000,7 @@ innobase_check_foreigns(
if (!new_field || (new_field->flags & NOT_NULL_FLAG)) {
if (innobase_check_foreigns_low(
user_table, drop_fk, n_drop_fk,
- (*fp)->field_name, !new_field)) {
+ (*fp)->field_name.str, !new_field)) {
return(true);
}
}
@@ -3262,7 +3262,7 @@ innobase_get_col_names(
}
if (new_field->field == table->field[old_i]) {
- cols[old_i - num_v] = new_field->field_name;
+ cols[old_i - num_v] = new_field->field_name.str;
break;
}
}
@@ -3550,7 +3550,7 @@ innobase_check_gis_columns(
ulint col_nr = dict_table_has_column(
table,
- key_part.field->field_name,
+ key_part.field->field_name.str,
key_part.fieldnr);
ut_ad(col_nr != table->n_def);
dict_col_t* col = &table->cols[col_nr];
@@ -3673,7 +3673,7 @@ prepare_inplace_add_virtual(
if (charset_no > MAX_CHAR_COLL_NUM) {
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
return(true);
}
} else {
@@ -3704,7 +3704,7 @@ prepare_inplace_add_virtual(
ctx->add_vcol[j].m_col.ind = i - 1;
ctx->add_vcol[j].num_base = 0;
- ctx->add_vcol_name[j] = field->field_name;
+ ctx->add_vcol_name[j] = field->field_name.str;
ctx->add_vcol[j].base_col = NULL;
ctx->add_vcol[j].v_pos = ctx->old_table->n_v_cols
- ctx->num_to_drop_vcol + j;
@@ -3792,7 +3792,7 @@ prepare_inplace_drop_virtual(
if (charset_no > MAX_CHAR_COLL_NUM) {
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
return(true);
}
} else {
@@ -3823,7 +3823,7 @@ prepare_inplace_drop_virtual(
ctx->drop_vcol[j].m_col.ind = i;
- ctx->drop_vcol_name[j] = field->field_name;
+ ctx->drop_vcol_name[j] = field->field_name.str;
dict_v_col_t* v_col = dict_table_get_nth_v_col_mysql(
ctx->old_table, i);
@@ -4640,7 +4640,7 @@ prepare_inplace_alter_table_dict(
dict_mem_table_free(
ctx->new_table);
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
goto new_clustered_failed;
}
} else {
@@ -4668,17 +4668,17 @@ prepare_inplace_alter_table_dict(
}
- if (dict_col_name_is_reserved(field->field_name)) {
+ if (dict_col_name_is_reserved(field->field_name.str)) {
dict_mem_table_free(ctx->new_table);
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
goto new_clustered_failed;
}
if (is_virtual) {
dict_mem_table_add_v_col(
ctx->new_table, ctx->heap,
- field->field_name,
+ field->field_name.str,
col_type,
dtype_form_prtype(
field_type, charset_no)
@@ -4687,7 +4687,7 @@ prepare_inplace_alter_table_dict(
} else {
dict_mem_table_add_col(
ctx->new_table, ctx->heap,
- field->field_name,
+ field->field_name.str,
col_type,
dtype_form_prtype(
field_type, charset_no),
@@ -5672,7 +5672,7 @@ err_exit_no_heap:
cf_it.rewind();
while (Create_field* cf = cf_it++) {
if (cf->field == *fp) {
- name = cf->field_name;
+ name = cf->field_name.str;
goto check_if_ok_to_rename;
}
}
@@ -5682,7 +5682,7 @@ check_if_ok_to_rename:
/* Prohibit renaming a column from FTS_DOC_ID
if full-text indexes exist. */
if (!my_strcasecmp(system_charset_info,
- (*fp)->field_name,
+ (*fp)->field_name.str,
FTS_DOC_ID_COL_NAME)
&& innobase_fulltext_exist(altered_table)) {
my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN,
@@ -7140,8 +7140,8 @@ innobase_rename_columns_try(
if (innobase_rename_column_try(
ctx->old_table, trx, table_name,
col_n,
- cf->field->field_name,
- cf->field_name,
+ cf->field->field_name.str,
+ cf->field_name.str,
ctx->need_rebuild(),
is_virtual)) {
return(true);
@@ -7365,8 +7365,8 @@ innobase_rename_or_enlarge_columns_cache(
if ((*fp)->flags & FIELD_IS_RENAMED) {
dict_mem_table_col_rename(
user_table, col_n,
- cf->field->field_name,
- cf->field_name, is_virtual);
+ cf->field->field_name.str,
+ cf->field_name.str, is_virtual);
}
break;
@@ -7417,7 +7417,7 @@ commit_set_autoinc(
const Field* ai = old_table->found_next_number_field;
ut_ad(!strcmp(dict_table_get_col_name(ctx->old_table,
innodb_col_no(ai)),
- ai->field_name));
+ ai->field_name.str));
ib_uint64_t autoinc
= ha_alter_info->create_info->auto_increment_value;
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 3a98280082f..e62a5e90ce2 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -42,6 +42,11 @@ enum {
/** sys fields will be found in the update vector or inserted
entry */
BTR_KEEP_SYS_FLAG = 4,
+
+ /** no rollback */
+ BTR_NO_ROLLBACK = BTR_NO_UNDO_LOG_FLAG
+ | BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG,
+
/** btr_cur_pessimistic_update() must keep cursor position
when moving columns to big_rec */
BTR_KEEP_POS_FLAG = 8,
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index 9aaf506b2e3..1377acb1e64 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -918,7 +918,8 @@ dict_tf_to_sys_tables_type(
| DICT_TF_MASK_ATOMIC_BLOBS
| DICT_TF_MASK_DATA_DIR
| DICT_TF_MASK_PAGE_COMPRESSION
- | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL);
+ | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL
+ | DICT_TF_MASK_NO_ROLLBACK);
return(type);
}
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index daa5af95a71..f78267a1465 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -144,10 +144,10 @@ Width of the page compression flag
#define DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL 4
/**
-Width of atomic writes flag
-DEFAULT=0, ON = 1, OFF = 2
+The NO_ROLLBACK flag (3=yes; the values 1,2 used stand for
+ATOMIC_WRITES=ON and ATOMIC_WRITES=OFF between MariaDB 10.1.0 and 10.2.3)
*/
-#define DICT_TF_WIDTH_ATOMIC_WRITES 2
+#define DICT_TF_WIDTH_NO_ROLLBACK 2
/** Width of all the currently known table flags */
#define DICT_TF_BITS (DICT_TF_WIDTH_COMPACT \
@@ -155,7 +155,8 @@ DEFAULT=0, ON = 1, OFF = 2
+ DICT_TF_WIDTH_ATOMIC_BLOBS \
+ DICT_TF_WIDTH_DATA_DIR \
+ DICT_TF_WIDTH_PAGE_COMPRESSION \
- + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL)
+ + DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL \
+ + DICT_TF_WIDTH_NO_ROLLBACK)
/** Zero relative shift position of the COMPACT field */
#define DICT_TF_POS_COMPACT 0
@@ -174,11 +175,11 @@ DEFAULT=0, ON = 1, OFF = 2
/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */
#define DICT_TF_POS_PAGE_COMPRESSION_LEVEL (DICT_TF_POS_PAGE_COMPRESSION \
+ DICT_TF_WIDTH_PAGE_COMPRESSION)
-/** Zero relative shift position of the ATOMIC_WRITES field */
-#define DICT_TF_POS_ATOMIC_WRITES (DICT_TF_POS_PAGE_COMPRESSION_LEVEL \
+/** Zero relative shift position of the NO_ROLLBACK field */
+#define DICT_TF_POS_NO_ROLLBACK (DICT_TF_POS_PAGE_COMPRESSION_LEVEL \
+ DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL)
-#define DICT_TF_POS_UNUSED (DICT_TF_POS_ATOMIC_WRITES \
- + DICT_TF_WIDTH_ATOMIC_WRITES)
+#define DICT_TF_POS_UNUSED (DICT_TF_POS_NO_ROLLBACK \
+ + DICT_TF_WIDTH_NO_ROLLBACK)
/** Bit mask of the COMPACT field */
#define DICT_TF_MASK_COMPACT \
@@ -204,10 +205,10 @@ DEFAULT=0, ON = 1, OFF = 2
#define DICT_TF_MASK_PAGE_COMPRESSION_LEVEL \
((~(~0U << DICT_TF_WIDTH_PAGE_COMPRESSION_LEVEL)) \
<< DICT_TF_POS_PAGE_COMPRESSION_LEVEL)
-/** Bit mask of the ATOMIC_WRITES field */
-#define DICT_TF_MASK_ATOMIC_WRITES \
- ((~(~0U << DICT_TF_WIDTH_ATOMIC_WRITES)) \
- << DICT_TF_POS_ATOMIC_WRITES)
+/** Bit mask of the NO_ROLLBACK field */
+#define DICT_TF_MASK_NO_ROLLBACK \
+ ((~(~0U << DICT_TF_WIDTH_NO_ROLLBACK)) \
+ << DICT_TF_POS_NO_ROLLBACK)
/** Return the value of the COMPACT field */
#define DICT_TF_GET_COMPACT(flags) \
@@ -233,10 +234,6 @@ DEFAULT=0, ON = 1, OFF = 2
#define DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags) \
((flags & DICT_TF_MASK_PAGE_COMPRESSION_LEVEL) \
>> DICT_TF_POS_PAGE_COMPRESSION_LEVEL)
-/** Return the value of the ATOMIC_WRITES field */
-#define DICT_TF_GET_ATOMIC_WRITES(flags) \
- ((flags & DICT_TF_MASK_ATOMIC_WRITES) \
- >> DICT_TF_POS_ATOMIC_WRITES)
/* @} */
@@ -1311,6 +1308,11 @@ struct dict_table_t {
/** Release the table handle. */
inline void release();
+ /** @return whether the table supports transactions */
+ bool no_rollback() const
+ {
+ return !(~flags & DICT_TF_MASK_NO_ROLLBACK);
+ }
/** @return whether this table is readable
@retval true normally
@retval false if this is a single-table tablespace
diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h
index 706579a3b9f..a860196e3db 100644
--- a/storage/innobase/include/ut0dbg.h
+++ b/storage/innobase/include/ut0dbg.h
@@ -62,7 +62,7 @@ ut_dbg_assertion_failed(
/** Debug assertion */
#define ut_ad DBUG_ASSERT
-#ifdef UNIV_DEBUG
+#if defined(UNIV_DEBUG) || !defined(DBUG_OFF)
/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
#define ut_d(EXPR) EXPR
#else
diff --git a/storage/innobase/include/ut0stage.h b/storage/innobase/include/ut0stage.h
index baad5cd77b4..a4ff0a1c874 100644
--- a/storage/innobase/include/ut0stage.h
+++ b/storage/innobase/include/ut0stage.h
@@ -272,7 +272,7 @@ current phase.
inline
void
ut_stage_alter_t::inc(
- ulint inc_val /* = 1 */)
+ ulint inc_val __attribute__((unused)) /* = 1 */)
{
if (m_progress == NULL) {
return;
diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc
index 5f9f57dc08a..5a3af9dfaeb 100644
--- a/storage/innobase/que/que0que.cc
+++ b/storage/innobase/que/que0que.cc
@@ -1032,6 +1032,7 @@ que_thr_step(
} else if (type == QUE_NODE_INSERT) {
thr = row_ins_step(thr);
} else if (type == QUE_NODE_UPDATE) {
+ trx_start_if_not_started_xa(thr_get_trx(thr), true);
thr = row_upd_step(thr);
} else if (type == QUE_NODE_FETCH) {
thr = fetch_step(thr);
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 15dc0b70733..df91ecc7a9b 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -3208,7 +3208,7 @@ row_ins_clust_index_entry(
log_free_check();
const ulint flags = dict_table_is_temporary(index->table)
? BTR_NO_LOCKING_FLAG
- : 0;
+ : index->table->no_rollback() ? BTR_NO_ROLLBACK : 0;
err = row_ins_clust_index_entry_low(
flags, BTR_MODIFY_LEAF, index, n_uniq, entry,
@@ -3742,7 +3742,27 @@ row_ins_step(
table during the search operation, and there is no need to set
it again here. But we must write trx->id to node->trx_id_buf. */
- memset(node->trx_id_buf, 0, DATA_TRX_ID_LEN);
+ if (node->table->no_rollback()) {
+ /* No-rollback tables should only be written to by a
+ single thread at a time, but there can be multiple
+ concurrent readers. We must hold an open table handle. */
+ DBUG_ASSERT(node->table->n_ref_count > 0);
+ DBUG_ASSERT(node->ins_type == INS_DIRECT);
+ /* No-rollback tables can consist only of a single index. */
+ DBUG_ASSERT(UT_LIST_GET_LEN(node->entry_list) == 1);
+ DBUG_ASSERT(UT_LIST_GET_LEN(node->table->indexes) == 1);
+ /* There should be no possibility for interruption and
+ restarting here. In theory, we could allow resumption
+ from the INS_NODE_INSERT_ENTRIES state here. */
+ DBUG_ASSERT(node->state == INS_NODE_SET_IX_LOCK);
+ memset(node->trx_id_buf, 0, DATA_TRX_ID_LEN);
+ memset(node->row_id_buf, 0, DATA_ROW_ID_LEN);
+ node->index = dict_table_get_first_index(node->table);
+ node->entry = UT_LIST_GET_FIRST(node->entry_list);
+ node->state = INS_NODE_INSERT_ENTRIES;
+ goto do_insert;
+ }
+
trx_write_trx_id(node->trx_id_buf, trx->id);
if (node->state == INS_NODE_SET_IX_LOCK) {
@@ -3792,7 +3812,7 @@ same_trx:
return(thr);
}
-
+do_insert:
/* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */
err = row_ins(node, thr);
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 08844bdd133..947b7d67df8 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1853,7 +1853,9 @@ row_update_for_mysql_using_upd_graph(
init_fts_doc_id_for_ref(table, &fk_depth);
- trx_start_if_not_started_xa(trx, true);
+ if (!table->no_rollback()) {
+ trx_start_if_not_started_xa(trx, true);
+ }
if (dict_table_is_referenced_by_foreign_key(table)) {
/* Share lock the data dictionary to prevent any
@@ -3674,7 +3676,7 @@ row_drop_table_for_mysql(
RemoteDatafile::delete_link_file(name);
}
- if (!dict_table_is_temporary(table)) {
+ if (!dict_table_is_temporary(table) && !table->no_rollback()) {
dict_stats_recalc_pool_del(table);
dict_stats_defrag_pool_del(table, NULL);
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 55278dd9406..03afd328eb5 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -4111,9 +4111,10 @@ row_search_mvcc(
ulint direction)
{
DBUG_ENTER("row_search_mvcc");
+ DBUG_ASSERT(prebuilt->index->table == prebuilt->table);
dict_index_t* index = prebuilt->index;
- ibool comp = dict_table_is_comp(index->table);
+ ibool comp = dict_table_is_comp(prebuilt->table);
const dtuple_t* search_tuple = prebuilt->search_tuple;
btr_pcur_t* pcur = prebuilt->pcur;
trx_t* trx = prebuilt->trx;
@@ -4434,17 +4435,19 @@ row_search_mvcc(
thread that is currently serving the transaction. Because we
are that thread, we can read trx->state without holding any
mutex. */
- ut_ad(prebuilt->sql_stat_start || trx->state == TRX_STATE_ACTIVE);
+ ut_ad(prebuilt->sql_stat_start
+ || trx->state == TRX_STATE_ACTIVE
+ || (prebuilt->table->no_rollback()
+ && trx->state == TRX_STATE_NOT_STARTED));
ut_ad(!trx_is_started(trx) || trx->state == TRX_STATE_ACTIVE);
ut_ad(prebuilt->sql_stat_start
|| prebuilt->select_lock_type != LOCK_NONE
|| MVCC::is_view_active(trx->read_view)
+ || prebuilt->table->no_rollback()
|| srv_read_only_mode);
- trx_start_if_not_started(trx, false);
-
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& prebuilt->select_lock_type != LOCK_NONE
&& trx->mysql_thd != NULL
@@ -4477,11 +4480,15 @@ row_search_mvcc(
que_thr_move_to_run_state_for_mysql(thr, trx);
- clust_index = dict_table_get_first_index(index->table);
+ clust_index = dict_table_get_first_index(prebuilt->table);
/* Do some start-of-statement preparations */
- if (!prebuilt->sql_stat_start) {
+ if (prebuilt->table->no_rollback()) {
+ /* NO_ROLLBACK tables do not support MVCC or locking. */
+ prebuilt->select_lock_type = LOCK_NONE;
+ prebuilt->sql_stat_start = FALSE;
+ } else if (!prebuilt->sql_stat_start) {
/* No need to set an intention lock or assign a read view */
if (!MVCC::is_view_active(trx->read_view)
@@ -4498,6 +4505,7 @@ row_search_mvcc(
} else if (prebuilt->select_lock_type == LOCK_NONE) {
/* This is a consistent read */
/* Assign a read view for the query */
+ trx_start_if_not_started(trx, false);
if (!srv_read_only_mode) {
trx_assign_read_view(trx);
@@ -4505,8 +4513,9 @@ row_search_mvcc(
prebuilt->sql_stat_start = FALSE;
} else {
+ trx_start_if_not_started(trx, false);
wait_table_again:
- err = lock_table(0, index->table,
+ err = lock_table(0, prebuilt->table,
prebuilt->select_lock_type == LOCK_S
? LOCK_IS : LOCK_IX, thr);
@@ -5035,7 +5044,8 @@ no_gap_lock:
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
- if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) {
+ if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED
+ || prebuilt->table->no_rollback()) {
/* Do nothing: we let a non-locking SELECT read the
latest version of the record */
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 4f57136db0b..34995faa2be 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2016, MariaDB Corporation.
+Copyright (c) 2015, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -2260,7 +2260,7 @@ row_upd_sec_index_entry(
flags = BTR_NO_LOCKING_FLAG;
mtr.set_log_mode(MTR_LOG_NO_REDO);
} else {
- flags = 0;
+ flags = index->table->no_rollback() ? BTR_NO_ROLLBACK : 0;
}
if (!index->is_committed()) {
@@ -3019,6 +3019,7 @@ row_upd_clust_step(
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets;
ibool referenced;
+ ulint flags;
ibool foreign = FALSE;
trx_t* trx = thr_get_trx(thr);
@@ -3040,14 +3041,16 @@ row_upd_clust_step(
mtr_start_trx(&mtr, thr_get_trx(thr));
mtr.set_named_space(index->space);
- /* Disable REDO logging as lifetime of temp-tables is limited to
- server or connection lifetime and so REDO information is not needed
- on restart for recovery.
- Disable locking as temp-tables are not shared across connection. */
- const ulint flags = dict_table_is_temporary(index->table)
- ? BTR_NO_LOCKING_FLAG : 0;
- if (flags) {
+ if (dict_table_is_temporary(node->table)) {
+ /* Disable locking, because temporary tables are
+ private to the connection (no concurrent access). */
+ flags = node->table->no_rollback()
+ ? BTR_NO_ROLLBACK
+ : BTR_NO_LOCKING_FLAG;
+ /* Redo logging only matters for persistent tables. */
mtr.set_log_mode(MTR_LOG_NO_REDO);
+ } else {
+ flags = node->table->no_rollback() ? BTR_NO_ROLLBACK : 0;
}
/* If the restoration does not succeed, then the same
@@ -3125,9 +3128,10 @@ row_upd_clust_step(
}
}
- ut_ad(lock_trx_has_rec_x_lock(thr_get_trx(thr), index->table,
- btr_pcur_get_block(pcur),
- page_rec_get_heap_no(rec)));
+ ut_ad(index->table->no_rollback()
+ || lock_trx_has_rec_x_lock(thr_get_trx(thr), index->table,
+ btr_pcur_get_block(pcur),
+ page_rec_get_heap_no(rec)));
/* NOTE: the following function calls will also commit mtr */
@@ -3327,8 +3331,6 @@ row_upd_step(
trx = thr_get_trx(thr);
- trx_start_if_not_started_xa(trx, true);
-
node = static_cast<upd_node_t*>(thr->run_node);
sel_node = node->select;
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 119a002a11a..3694fe591ce 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -990,7 +990,8 @@ int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_FILE_BASED | HA_CAN_GEOMETRY | CANNOT_ROLLBACK_FLAG |
HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | HA_CAN_REPAIR |
HA_CAN_VIRTUAL_COLUMNS |
- HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT),
+ HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT |
+ HA_CAN_TABLES_WITHOUT_ROLLBACK),
can_enable_indexes(1), bulk_insert_single_undo(BULK_INSERT_NONE)
{}
@@ -2273,7 +2274,7 @@ bool ha_maria::check_and_repair(THD *thd)
if (!file->state->del && (maria_recover_options & HA_RECOVER_QUICK))
check_opt.flags |= T_QUICK;
- thd->set_query(table->s->table_name.str,
+ thd->set_query((char*) table->s->table_name.str,
(uint) table->s->table_name.length, system_charset_info);
if (!(crashed= maria_is_crashed(file)))
@@ -2309,14 +2310,14 @@ bool ha_maria::is_crashed() const
#define CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING(msg) \
do { \
- if (file->lock.type == TL_WRITE_CONCURRENT_INSERT) \
+ if (file->lock.type == TL_WRITE_CONCURRENT_INSERT && !table->s->sequence) \
{ \
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), msg); \
return 1; \
} \
} while(0)
-int ha_maria::update_row(const uchar * old_data, uchar * new_data)
+int ha_maria::update_row(const uchar * old_data, const uchar * new_data)
{
CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("UPDATE in WRITE CONCURRENT");
return maria_update(file, old_data, new_data);
@@ -3105,6 +3106,13 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
ER_ILLEGAL_HA_CREATE_OPTION,
"Row format set to PAGE because of TRANSACTIONAL=1 option");
+ if (share->table_type == TABLE_TYPE_SEQUENCE)
+ {
+ /* For sequences, the simples record type is appropriate */
+ row_type= STATIC_RECORD;
+ ha_create_info->transactional= HA_CHOICE_NO;
+ }
+
bzero((char*) &create_info, sizeof(create_info));
if ((error= table2maria(table_arg, row_type, &keydef, &recinfo,
&record_count, &create_info)))
@@ -3401,7 +3409,7 @@ bool maria_show_status(handlerton *hton,
stat_print_fn *print,
enum ha_stat_type stat)
{
- const LEX_STRING *engine_name= hton_name(hton);
+ const LEX_CSTRING *engine_name= hton_name(hton);
switch (stat) {
case HA_ENGINE_LOGS:
{
@@ -3641,7 +3649,7 @@ static int ha_maria_init(void *p)
@retval FALSE An error occurred
*/
-my_bool ha_maria::register_query_cache_table(THD *thd, char *table_name,
+my_bool ha_maria::register_query_cache_table(THD *thd, const char *table_name,
uint table_name_len,
qc_engine_callback
*engine_callback,
@@ -3926,6 +3934,36 @@ Item *ha_maria::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
return NULL;
}
+/**
+ Find record by unique constrain (used in temporary tables)
+
+ @param record (IN|OUT) the record to find
+ @param constrain_no (IN) number of constrain (for this engine)
+
+ @note It is like hp_search but uses function for raw where hp_search
+ uses functions for index.
+
+ @retval 0 OK
+ @retval 1 Not found
+ @retval -1 Error
+*/
+
+int ha_maria::find_unique_row(uchar *record, uint constrain_no)
+{
+ MARIA_UNIQUEDEF *def= file->s->uniqueinfo + constrain_no;
+ ha_checksum unique_hash= _ma_unique_hash(def, record);
+ int rc= _ma_check_unique(file, def, record, unique_hash, HA_OFFSET_ERROR);
+ if (rc)
+ {
+ file->cur_row.lastpos= file->dup_key_pos;
+ if ((*file->read_record)(file, record, file->cur_row.lastpos))
+ return -1;
+ file->update|= HA_STATE_AKTIV; /* Record is read */
+ }
+ // invert logic
+ return (rc ? 0 : 1);
+}
+
struct st_mysql_storage_engine maria_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
index 65fe5f545d1..51438462787 100644
--- a/storage/maria/ha_maria.h
+++ b/storage/maria/ha_maria.h
@@ -75,7 +75,7 @@ public:
int open(const char *name, int mode, uint test_if_locked);
int close(void);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map,
enum ha_rkey_function find_flag);
@@ -162,7 +162,7 @@ public:
int net_read_dump(NET * net);
#endif
#ifdef HAVE_QUERY_CACHE
- my_bool register_query_cache_table(THD *thd, char *table_key,
+ my_bool register_query_cache_table(THD *thd, const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
@@ -190,6 +190,8 @@ public:
/* Index condition pushdown implementation */
Item *idx_cond_push(uint keyno, Item* idx_cond);
+
+ int find_unique_row(uchar *record, uint unique_idx);
private:
DsMrr_impl ds_mrr;
friend ICP_RESULT index_cond_func_maria(void *arg);
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 80e38fc2b00..e4cf20bf685 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -55,7 +55,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
uint internal_table= flags & HA_CREATE_INTERNAL_TABLE;
ulong reclength, real_reclength,min_pack_length;
char kfilename[FN_REFLEN], klinkname[FN_REFLEN], *klinkname_ptr;
- char dfilename[FN_REFLEN], dlinkname[FN_REFLEN], *dlinkname_ptr;
+ char dfilename[FN_REFLEN], dlinkname[FN_REFLEN], *dlinkname_ptr= 0;
ulong pack_reclength;
ulonglong tot_length,max_rows, tmp;
enum en_fieldtype type;
diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c
index 51f27520dc1..ddf2a7251ab 100644
--- a/storage/maria/ma_ft_update.c
+++ b/storage/maria/ma_ft_update.c
@@ -28,6 +28,8 @@ void _ma_ft_segiterator_init(MARIA_HA *info, uint keynr, const uchar *record,
ftsi->num=info->s->keyinfo[keynr].keysegs;
ftsi->seg=info->s->keyinfo[keynr].seg;
ftsi->rec=record;
+ ftsi->pos= 0; /* Avoid warnings from gcc */
+ ftsi->len= 0; /* Avoid warnings from gcc */
DBUG_VOID_RETURN;
}
diff --git a/storage/maria/ma_unique.c b/storage/maria/ma_unique.c
index 72104e25e3f..dfbb471f31e 100644
--- a/storage/maria/ma_unique.c
+++ b/storage/maria/ma_unique.c
@@ -27,8 +27,9 @@
isn't any versioning information.
*/
-my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record,
- ha_checksum unique_hash, my_off_t disk_pos)
+my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def,
+ const uchar *record,
+ ha_checksum unique_hash, my_off_t disk_pos)
{
my_off_t lastpos=info->cur_row.lastpos;
MARIA_KEYDEF *keyinfo= &info->s->keyinfo[def->key];
@@ -38,6 +39,7 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record,
DBUG_ENTER("_ma_check_unique");
DBUG_PRINT("enter",("unique_hash: %lu", (ulong) unique_hash));
+ /* We need to store the hash value as a key in the record, breaking const */
maria_unique_store(record+keyinfo->seg->start, unique_hash);
/* Can't be spatial so it's ok to call _ma_make_key directly here */
_ma_make_key(info, &key, def->key, key_buff, record, 0, 0);
diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c
index 0e006d2473d..6e150f727d6 100644
--- a/storage/maria/ma_update.c
+++ b/storage/maria/ma_update.c
@@ -21,7 +21,8 @@
Update an old row in a MARIA table
*/
-int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
+int maria_update(register MARIA_HA *info, const uchar *oldrec,
+ const uchar *newrec)
{
int flag,key_changed,save_errno;
reg3 my_off_t pos;
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index cc100b3706c..6f8964fd479 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -1324,7 +1324,7 @@ ulong _ma_calc_total_blob_length(MARIA_HA *info, const uchar *record);
ha_checksum _ma_checksum(MARIA_HA *info, const uchar *buf);
ha_checksum _ma_static_checksum(MARIA_HA *info, const uchar *buf);
my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def,
- uchar *record, ha_checksum unique_hash,
+ const uchar *record, ha_checksum unique_hash,
MARIA_RECORD_POS pos);
ha_checksum _ma_unique_hash(MARIA_UNIQUEDEF *def, const uchar *buf);
my_bool _ma_cmp_static_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def,
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp
index 27a3e7b3294..cb353db53b0 100644
--- a/storage/mroonga/ha_mroonga.cpp
+++ b/storage/mroonga/ha_mroonga.cpp
@@ -463,6 +463,9 @@ static const char *mrn_inspect_extra_function(enum ha_extra_function operation)
case HA_EXTRA_PREPARE_FOR_DROP:
inspected = "HA_EXTRA_PREPARE_FOR_DROP";
break;
+ case HA_EXTRA_PREPARE_FOR_ALTER_TABLE:
+ inspected = "HA_EXTRA_PREPARE_FOR_ALTER_TABLE";
+ break;
case HA_EXTRA_PREPARE_FOR_UPDATE:
inspected = "HA_EXTRA_PREPARE_FOR_UPDATE";
break;
@@ -3213,7 +3216,7 @@ int ha_mroonga::storage_create(const char *name, TABLE *table,
int key_parts = KEY_N_KEY_PARTS(key_info);
if (key_parts == 1) {
Field *pkey_field = key_info->key_part[0].field;
- const char *column_name = pkey_field->field_name;
+ const char *column_name = pkey_field->field_name.str;
is_id = (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0);
grn_builtin_type gtype = mrn_grn_type_from_field(ctx, pkey_field, false);
@@ -3307,7 +3310,7 @@ int ha_mroonga::storage_create(const char *name, TABLE *table,
uint n_columns = table->s->fields;
for (uint i = 0; i < n_columns; i++) {
Field *field = table->s->field[i];
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
int column_name_size = strlen(column_name);
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
@@ -3374,7 +3377,7 @@ int ha_mroonga::storage_create_validate_pseudo_column(TABLE *table)
n_columns = table->s->fields;
for (i = 0; i < n_columns; i++) {
Field *field = table->s->field[i];
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
switch (field->type()) {
case MYSQL_TYPE_TINY :
@@ -3422,17 +3425,17 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
}
List_iterator<Key_part_spec> key_part_col_iterator(key->columns);
Key_part_spec *key_part_col = key_part_col_iterator++;
- LEX_STRING field_name = key_part_col->field_name;
+ LEX_CSTRING field_name = key_part_col->field_name;
DBUG_PRINT("info", ("mroonga: field_name=%s", field_name.str));
- DBUG_PRINT("info", ("mroonga: field->field_name=%s", field->field_name));
- if (strcmp(field->field_name, field_name.str))
+ DBUG_PRINT("info", ("mroonga: field->field_name=%s", field->field_name.str));
+ if (strcmp(field->field_name.str, field_name.str))
{
continue;
}
Foreign_key *fk = (Foreign_key *) key;
List_iterator<Key_part_spec> key_part_ref_col_iterator(fk->ref_columns);
Key_part_spec *key_part_ref_col = key_part_ref_col_iterator++;
- LEX_STRING ref_field_name = key_part_ref_col->field_name;
+ LEX_CSTRING ref_field_name = key_part_ref_col->field_name;
DBUG_PRINT("info", ("mroonga: ref_field_name=%s", ref_field_name.str));
#ifdef MRN_FOREIGN_KEY_USE_CONST_STRING
LEX_CSTRING ref_db_name = fk->ref_db;
@@ -3537,7 +3540,7 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
DBUG_RETURN(false);
}
Field *ref_field = &ref_key_info->key_part->field[0];
- if (strcmp(ref_field->field_name, ref_field_name.str)) {
+ if (strcmp(ref_field->field_name.str, ref_field_name.str)) {
mrn_open_mutex_lock(table->s);
mrn_free_tmp_table_share(tmp_ref_table_share);
mrn_open_mutex_unlock(table->s);
@@ -3554,8 +3557,8 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
mrn_free_tmp_table_share(tmp_ref_table_share);
mrn_open_mutex_unlock(table->s);
grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
- column = grn_column_create(ctx, table_obj, field->field_name,
- strlen(field->field_name),
+ column = grn_column_create(ctx, table_obj, field->field_name.str,
+ field->field_name.length,
NULL, col_flags, grn_table_ref);
if (ctx->rc) {
grn_obj_unlink(ctx, grn_table_ref);
@@ -3564,7 +3567,7 @@ bool ha_mroonga::storage_create_foreign_key(TABLE *table,
DBUG_RETURN(false);
}
- mrn::IndexColumnName index_column_name(grn_table_name, field->field_name);
+ mrn::IndexColumnName index_column_name(grn_table_name, field->field_name.str);
grn_obj_flags ref_col_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT;
column_ref = grn_column_create(ctx, grn_table_ref,
index_column_name.c_str(),
@@ -3618,7 +3621,7 @@ int ha_mroonga::storage_create_validate_index(TABLE *table)
continue;
}
Field *field = key_info->key_part[0].field;
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
if (key_info->algorithm == HA_KEY_ALG_HASH) {
continue; // hash index is ok
@@ -3755,8 +3758,8 @@ int ha_mroonga::storage_create_index(TABLE *table, const char *grn_table_name,
bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
if (!is_multiple_column_index) {
Field *field = key_info->key_part[0].field;
- column_name = field->field_name;
- column_name_size = strlen(column_name);
+ column_name = field->field_name.str;
+ column_name_size = field->field_name.length;
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
// skipping _id virtual column
DBUG_RETURN(0);
@@ -3813,8 +3816,8 @@ int ha_mroonga::storage_create_index(TABLE *table, const char *grn_table_name,
int j, n_key_parts = KEY_N_KEY_PARTS(key_info);
for (j = 0; j < n_key_parts; j++) {
Field *field = key_info->key_part[j].field;
- const char *column_name = field->field_name;
- int column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ int column_name_size = field->field_name.length;
grn_obj *source_column = grn_obj_column(ctx, grn_table,
column_name, column_name_size);
grn_id source_id = grn_obj_id(ctx, source_column);
@@ -4113,8 +4116,8 @@ int ha_mroonga::wrapper_open_indexes(const char *name)
/* just for backward compatibility before 1.0. */
Field *field = key_info->key_part[0].field;
grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i],
- field->field_name,
- strlen(field->field_name));
+ field->field_name.str,
+ field->field_name.length);
}
if (ctx->rc) {
@@ -4294,8 +4297,8 @@ int ha_mroonga::storage_open_columns(void)
for (int i = 0; i < n_columns; i++) {
Field *field = table->field[i];
- const char *column_name = field->field_name;
- int column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ int column_name_size = field->field_name.length;
if (table_share->blob_fields)
{
blob_buffers[i].set_charset(field->charset());
@@ -4409,8 +4412,8 @@ int ha_mroonga::storage_open_indexes(const char *name)
/* just for backward compatibility before 1.0. */
Field *field = key_info->key_part[0].field;
grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i],
- field->field_name,
- strlen(field->field_name));
+ field->field_name.str,
+ field->field_name.length);
}
}
}
@@ -5401,7 +5404,7 @@ int ha_mroonga::storage_write_row(uchar *buf)
mrn::DebugColumnAccess debug_column_access(table, table->read_set);
for (i = 0; i < n_columns; i++) {
Field *field = table->field[i];
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (field->is_null()) continue;
@@ -5495,7 +5498,7 @@ int ha_mroonga::storage_write_row(uchar *buf)
GRN_VOID_INIT(&colbuf);
for (i = 0; i < n_columns; i++) {
Field *field = table->field[i];
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (field->is_null())
continue;
@@ -5674,7 +5677,7 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::storage_write_row_unique_index(uchar *buf,
+int ha_mroonga::storage_write_row_unique_index(const uchar *buf,
KEY *key_info,
grn_obj *index_table,
grn_obj *index_column,
@@ -5856,7 +5859,8 @@ int ha_mroonga::wrapper_get_record_id(uchar *data, grn_id *record_id,
DBUG_RETURN(error);
}
-int ha_mroonga::wrapper_update_row(const uchar *old_data, uchar *new_data)
+int ha_mroonga::wrapper_update_row(const uchar *old_data,
+ const uchar *new_data)
{
MRN_DBUG_ENTER_METHOD();
@@ -5877,7 +5881,8 @@ int ha_mroonga::wrapper_update_row(const uchar *old_data, uchar *new_data)
DBUG_RETURN(error);
}
-int ha_mroonga::wrapper_update_row_index(const uchar *old_data, uchar *new_data)
+int ha_mroonga::wrapper_update_row_index(const uchar *old_data,
+ const uchar *new_data)
{
MRN_DBUG_ENTER_METHOD();
@@ -5989,7 +5994,8 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::storage_update_row(const uchar *old_data, uchar *new_data)
+int ha_mroonga::storage_update_row(const uchar *old_data,
+ const uchar *new_data)
{
MRN_DBUG_ENTER_METHOD();
int error = 0;
@@ -6007,7 +6013,7 @@ int ha_mroonga::storage_update_row(const uchar *old_data, uchar *new_data)
for (i = 0; i < n_columns; i++) {
Field *field = table->field[i];
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (bitmap_is_set(table->write_set, field->field_index)) {
if (field->is_null()) continue;
@@ -6044,7 +6050,7 @@ int ha_mroonga::storage_update_row(const uchar *old_data, uchar *new_data)
GRN_VOID_INIT(&colbuf);
for (i = 0; i < n_columns; i++) {
Field *field = table->field[i];
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (bitmap_is_set(table->write_set, field->field_index)) {
mrn::DebugColumnAccess debug_column_access(table, table->read_set);
DBUG_PRINT("info", ("mroonga: update column %d(%d)",i,field->field_index));
@@ -6065,7 +6071,7 @@ int ha_mroonga::storage_update_row(const uchar *old_data, uchar *new_data)
bool have_pkey = false;
for (j = 0; j < KEY_N_KEY_PARTS(pkey_info); j++) {
Field *pkey_field = pkey_info->key_part[j].field;
- if (strcmp(pkey_field->field_name, column_name) == 0) {
+ if (strcmp(pkey_field->field_name.str, column_name) == 0) {
if (!replacing_) {
char message[MRN_BUFFER_SIZE];
snprintf(message, MRN_BUFFER_SIZE,
@@ -6152,7 +6158,8 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::storage_update_row_index(const uchar *old_data, uchar *new_data)
+int ha_mroonga::storage_update_row_index(const uchar *old_data,
+ const uchar *new_data)
{
MRN_DBUG_ENTER_METHOD();
int error = 0;
@@ -6244,7 +6251,7 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data)
+int ha_mroonga::storage_update_row_unique_indexes(const uchar *new_data)
{
int error;
uint i;
@@ -6321,7 +6328,7 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::update_row(const uchar *old_data, uchar *new_data)
+int ha_mroonga::update_row(const uchar *old_data, const uchar *new_data)
{
MRN_DBUG_ENTER_METHOD();
int error = 0;
@@ -6734,7 +6741,7 @@ ha_rows ha_mroonga::storage_records_in_range(uint key_nr, key_range *range_min,
DBUG_RETURN(row_count);
} else {
Field *field = key_info->key_part[0].field;
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
mrn_change_encoding(ctx, field->charset());
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
@@ -7026,7 +7033,7 @@ int ha_mroonga::storage_index_read_map(uchar *buf, const uchar *key,
DBUG_RETURN(error);
if (find_flag == HA_READ_KEY_EXACT) {
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
key_min = key_min_entity;
key_max = key_min_entity;
@@ -7578,7 +7585,7 @@ int ha_mroonga::storage_read_range_first(const key_range *start_key,
}
} else {
Field *field = key_info->key_part[0].field;
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
error = mrn_change_encoding(ctx, field->charset());
if (error)
DBUG_RETURN(error);
@@ -9108,7 +9115,7 @@ grn_obj *ha_mroonga::find_column_type(Field *field, MRN_SHARE *mrn_share, int i,
char error_message[MRN_BUFFER_SIZE];
snprintf(error_message, MRN_BUFFER_SIZE,
"unknown custom Groonga type name for <%s> column: <%s>",
- field->field_name, grn_type_name);
+ field->field_name.str, grn_type_name);
GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
my_message(error_code, error_message, MYF(0));
@@ -9786,8 +9793,8 @@ bool ha_mroonga::is_primary_key_field(Field *field) const
DBUG_RETURN(false);
}
- if (strcmp(field->field_name,
- key_info->key_part[0].field->field_name) == 0) {
+ if (strcmp(field->field_name.str,
+ key_info->key_part[0].field->field_name.str) == 0) {
DBUG_RETURN(true);
} else {
DBUG_RETURN(false);
@@ -9890,8 +9897,8 @@ void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys,
if (item->type() == Item::FIELD_ITEM)
{
Field *field = static_cast<Item_field *>(item)->field;
- const char *column_name = field->field_name;
- int column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ int column_name_size = field->field_name.length;
if (should_normalize(field))
{
@@ -10984,11 +10991,11 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id)
if (bitmap_is_set(table->read_set, field->field_index) ||
bitmap_is_set(table->write_set, field->field_index)) {
- const char *column_name = field->field_name;
+ const char *column_name = field->field_name.str;
if (ignoring_no_key_columns) {
KEY *key_info = &(table->s->key_info[active_index]);
- if (strcmp(key_info->key_part[0].field->field_name, column_name)) {
+ if (strcmp(key_info->key_part[0].field->field_name.str, column_name)) {
continue;
}
}
@@ -11001,7 +11008,7 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id)
field->set_notnull();
field->store((int)record_id);
} else if (primary_key_field &&
- strcmp(primary_key_field->field_name, column_name) == 0) {
+ strcmp(primary_key_field->field_name.str, column_name) == 0) {
// for primary key column
storage_store_field_column(field, true, i, record_id);
} else {
@@ -11015,7 +11022,7 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id)
}
void ha_mroonga::storage_store_fields_for_prep_update(const uchar *old_data,
- uchar *new_data,
+ const uchar *new_data,
grn_id record_id)
{
MRN_DBUG_ENTER_METHOD();
@@ -11464,7 +11471,8 @@ int ha_mroonga::storage_encode_key_set(Field *field, const uchar *key,
MRN_DBUG_ENTER_METHOD();
int error = 0;
Field_set unpacker((uchar *)key, field->field_length, (uchar *)(key - 1),
- field->null_bit, field->unireg_check, field->field_name,
+ field->null_bit, field->unireg_check,
+ &field->field_name,
field->pack_length(),
static_cast<Field_set*>(field)->typelib,
static_cast<Field_set*>(field)->charset());
@@ -12899,8 +12907,8 @@ int ha_mroonga::storage_rename_foreign_key(MRN_SHARE *tmp_share,
MRN_DBUG_ENTER_METHOD();
for (i = 0; i < n_columns; ++i) {
Field *field = tmp_table_share->field[i];
- const char *column_name = field->field_name;
- uint column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ uint column_name_size = field->field_name.length;
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
continue;
@@ -14566,8 +14574,8 @@ bool ha_mroonga::storage_inplace_alter_table_add_column(
}
Field *field = altered_table->s->field[i];
- const char *column_name = field->field_name;
- int column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ int column_name_size = field->field_name.length;
int error = mrn_add_column_param(tmp_share, field, i);
if (error) {
@@ -14647,8 +14655,8 @@ bool ha_mroonga::storage_inplace_alter_table_drop_column(
continue;
}
- const char *column_name = field->field_name;
- int column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ int column_name_size = field->field_name.length;
grn_obj *column_obj;
column_obj = grn_obj_column(ctx, table_obj, column_name, column_name_size);
@@ -14688,7 +14696,8 @@ bool ha_mroonga::storage_inplace_alter_table_rename_column(
continue;
}
- const char *new_name = NULL;
+ LEX_CSTRING new_name;
+ new_name.str= 0;
List_iterator_fast<Create_field> create_fields(alter_info->create_list);
while (Create_field *create_field = create_fields++) {
if (create_field->field == field) {
@@ -14697,15 +14706,16 @@ bool ha_mroonga::storage_inplace_alter_table_rename_column(
}
}
- if (!new_name) {
+ if (!new_name.str) {
continue;
}
- const char *old_name = field->field_name;
+ const char *old_name = field->field_name.str;
grn_obj *column_obj;
- column_obj = grn_obj_column(ctx, table_obj, old_name, strlen(old_name));
+ column_obj = grn_obj_column(ctx, table_obj, old_name,
+ field->field_name.length);
if (column_obj) {
- grn_column_rename(ctx, column_obj, new_name, strlen(new_name));
+ grn_column_rename(ctx, column_obj, new_name.str, new_name.length);
if (ctx->rc) {
int error = ER_WRONG_COLUMN_NAME;
my_message(error, ctx->errbuf, MYF(0));
@@ -15874,8 +15884,8 @@ char *ha_mroonga::storage_get_foreign_key_create_info()
create_info_str.length(0);
for (i = 0; i < n_columns; ++i) {
Field *field = table_share->field[i];
- const char *column_name = field->field_name;
- uint column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ uint column_name_size = field->field_name.length;
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
continue;
@@ -15949,8 +15959,8 @@ char *ha_mroonga::storage_get_foreign_key_create_info()
uint ref_pkey_nr = tmp_ref_table_share->primary_key;
KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
Field *ref_field = &ref_key_info->key_part->field[0];
- append_identifier(ha_thd(), &create_info_str, ref_field->field_name,
- strlen(ref_field->field_name));
+ append_identifier(ha_thd(), &create_info_str, ref_field->field_name.str,
+ ref_field->field_name.length);
mrn_open_mutex_lock(table_share);
mrn_free_tmp_table_share(tmp_ref_table_share);
mrn_open_mutex_unlock(table_share);
@@ -16081,8 +16091,8 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
MRN_DBUG_ENTER_METHOD();
for (i = 0; i < n_columns; ++i) {
Field *field = table_share->field[i];
- const char *column_name = field->field_name;
- uint column_name_size = strlen(column_name);
+ const char *column_name = field->field_name.str;
+ uint column_name_size = field->field_name.length;
if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
continue;
@@ -16128,7 +16138,7 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
f_key_info.delete_method = FK_OPTION_RESTRICT;
f_key_info.referenced_key_name = thd_make_lex_string(thd, NULL, "PRIMARY",
7, TRUE);
- LEX_STRING *field_name = thd_make_lex_string(thd, NULL, column_name,
+ LEX_CSTRING *field_name = thd_make_lex_string(thd, NULL, column_name,
column_name_size, TRUE);
f_key_info.foreign_fields.push_back(field_name);
@@ -16153,9 +16163,9 @@ int ha_mroonga::storage_get_foreign_key_list(THD *thd,
uint ref_pkey_nr = tmp_ref_table_share->primary_key;
KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
Field *ref_field = &ref_key_info->key_part->field[0];
- LEX_STRING *ref_col_name = thd_make_lex_string(thd, NULL,
- ref_field->field_name,
- strlen(ref_field->field_name),
+ LEX_CSTRING *ref_col_name = thd_make_lex_string(thd, NULL,
+ ref_field->field_name.str,
+ ref_field->field_name.length,
TRUE);
f_key_info.referenced_fields.push_back(ref_col_name);
mrn_open_mutex_lock(table_share);
@@ -16428,7 +16438,7 @@ void ha_mroonga::rebind_psi()
#endif
my_bool ha_mroonga::wrapper_register_query_cache_table(THD *thd,
- char *table_key,
+ const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
@@ -16449,7 +16459,7 @@ my_bool ha_mroonga::wrapper_register_query_cache_table(THD *thd,
}
my_bool ha_mroonga::storage_register_query_cache_table(THD *thd,
- char *table_key,
+ const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
@@ -16465,7 +16475,7 @@ my_bool ha_mroonga::storage_register_query_cache_table(THD *thd,
}
my_bool ha_mroonga::register_query_cache_table(THD *thd,
- char *table_key,
+ const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
diff --git a/storage/mroonga/ha_mroonga.hpp b/storage/mroonga/ha_mroonga.hpp
index 37059210dd1..6416513f0eb 100644
--- a/storage/mroonga/ha_mroonga.hpp
+++ b/storage/mroonga/ha_mroonga.hpp
@@ -192,7 +192,7 @@ extern "C" {
# define MRN_HAVE_HTON_ALTER_TABLE_FLAGS
#endif
-#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
+#if MYSQL_VERSION_ID >= 50706
# define MRN_FOREIGN_KEY_USE_CONST_STRING
#endif
@@ -384,7 +384,7 @@ public:
int delete_table(const char *name);
int write_row(uchar *buf);
- int update_row(const uchar *old_data, uchar *new_data);
+ int update_row(const uchar *old_data, const uchar *new_data);
int delete_row(const uchar *buf);
uint max_supported_record_length() const;
@@ -559,7 +559,7 @@ protected:
void rebind_psi();
#endif
my_bool register_query_cache_table(THD *thd,
- char *table_key,
+ const char *table_key,
uint key_length,
qc_engine_callback *engine_callback,
ulonglong *engine_data);
@@ -692,7 +692,7 @@ private:
int nth_column, grn_id record_id);
void storage_store_fields(uchar *buf, grn_id record_id);
void storage_store_fields_for_prep_update(const uchar *old_data,
- uchar *new_data,
+ const uchar *new_data,
grn_id record_id);
void storage_store_fields_by_index(uchar *buf);
@@ -827,18 +827,21 @@ private:
KEY *key_info,
grn_obj *index_column);
int storage_write_row_multiple_column_indexes(uchar *buf, grn_id record_id);
- int storage_write_row_unique_index(uchar *buf,
+ int storage_write_row_unique_index(const uchar *buf,
KEY *key_info,
grn_obj *index_table,
grn_obj *index_column,
grn_id *key_id);
int storage_write_row_unique_indexes(uchar *buf);
- int wrapper_get_record_id(uchar *data, grn_id *record_id, const char *context);
- int wrapper_update_row(const uchar *old_data, uchar *new_data);
- int wrapper_update_row_index(const uchar *old_data, uchar *new_data);
- int storage_update_row(const uchar *old_data, uchar *new_data);
- int storage_update_row_index(const uchar *old_data, uchar *new_data);
- int storage_update_row_unique_indexes(uchar *new_data);
+ int wrapper_get_record_id(uchar *data, grn_id *record_id,
+ const char *context);
+ int wrapper_update_row(const uchar *old_data, const uchar *new_data);
+ int wrapper_update_row_index(const uchar *old_data,
+ const uchar *new_data);
+ int storage_update_row(const uchar *old_data, const uchar *new_data);
+ int storage_update_row_index(const uchar *old_data,
+ const uchar *new_data);
+ int storage_update_row_unique_indexes(const uchar *new_data);
int wrapper_delete_row(const uchar *buf);
int wrapper_delete_row_index(const uchar *buf);
int storage_delete_row(const uchar *buf);
@@ -1216,13 +1219,13 @@ private:
void storage_rebind_psi();
#endif
my_bool wrapper_register_query_cache_table(THD *thd,
- char *table_key,
+ const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
ulonglong *engine_data);
my_bool storage_register_query_cache_table(THD *thd,
- char *table_key,
+ const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
diff --git a/storage/mroonga/lib/mrn_condition_converter.cpp b/storage/mroonga/lib/mrn_condition_converter.cpp
index 1527a546938..cd739b15e51 100644
--- a/storage/mroonga/lib/mrn_condition_converter.cpp
+++ b/storage/mroonga/lib/mrn_condition_converter.cpp
@@ -28,8 +28,8 @@
# define MRN_ITEM_FIELD_GET_NAME(item) ((item)->item_name.ptr())
# define MRN_ITEM_FIELD_GET_NAME_LENGTH(item) ((item)->item_name.length())
#else
-# define MRN_ITEM_FIELD_GET_NAME(item) ((item)->name)
-# define MRN_ITEM_FIELD_GET_NAME_LENGTH(item) (strlen((item)->name))
+# define MRN_ITEM_FIELD_GET_NAME(item) ((item)->name.str)
+# define MRN_ITEM_FIELD_GET_NAME_LENGTH(item) ((item)->name.length)
#endif
namespace mrn {
diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp
index 2b29c46be77..8984db3bfbf 100644
--- a/storage/mroonga/mrn_table.cpp
+++ b/storage/mroonga/mrn_table.cpp
@@ -468,7 +468,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table)
if (share->engine)
{
- LEX_STRING engine_name;
+ LEX_CSTRING engine_name;
if (
(
share->engine_length == MRN_DEFAULT_LEN &&
@@ -1066,9 +1066,9 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path
void mrn_free_tmp_table_share(TABLE_SHARE *tmp_table_share)
{
MRN_DBUG_ENTER_FUNCTION();
- char *normalized_path = tmp_table_share->normalized_path.str;
+ const char *normalized_path = tmp_table_share->normalized_path.str;
free_table_share(tmp_table_share);
- my_free(normalized_path);
+ my_free((char*) normalized_path);
DBUG_VOID_RETURN;
}
diff --git a/storage/myisam/ft_update.c b/storage/myisam/ft_update.c
index 8f437476121..f851c0236ae 100644
--- a/storage/myisam/ft_update.c
+++ b/storage/myisam/ft_update.c
@@ -28,6 +28,8 @@ void _mi_ft_segiterator_init(MI_INFO *info, uint keynr, const uchar *record,
ftsi->num=info->s->keyinfo[keynr].keysegs;
ftsi->seg=info->s->keyinfo[keynr].seg;
ftsi->rec=record;
+ ftsi->pos= 0; /* Avoid warnings from gcc */
+ ftsi->len= 0; /* Avoid warnings from gcc */
DBUG_VOID_RETURN;
}
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 213b1dc9ec3..2941eb9e43f 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -696,7 +696,8 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
- HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_REPAIR),
+ HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_REPAIR |
+ HA_CAN_TABLES_WITHOUT_ROLLBACK),
can_enable_indexes(1)
{}
@@ -1752,7 +1753,7 @@ bool ha_myisam::check_and_repair(THD *thd)
sql_print_warning("Checking table: '%s'",table->s->path.str);
const CSET_STRING query_backup= thd->query_string;
- thd->set_query(table->s->table_name.str,
+ thd->set_query((char*) table->s->table_name.str,
(uint) table->s->table_name.length, system_charset_info);
if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt))
@@ -1790,7 +1791,7 @@ bool ha_myisam::is_crashed() const
(my_disable_locking && file->s->state.open_count));
}
-int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
+int ha_myisam::update_row(const uchar *old_data, const uchar *new_data)
{
return mi_update(file,old_data,new_data);
}
@@ -2588,7 +2589,7 @@ maria_declare_plugin_end;
@retval FALSE An error occurred
*/
-my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name,
+my_bool ha_myisam::register_query_cache_table(THD *thd, const char *table_name,
uint table_name_len,
qc_engine_callback
*engine_callback,
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index 4068720e39e..804963f5efc 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -71,7 +71,7 @@ class ha_myisam: public handler
int open(const char *name, int mode, uint test_if_locked);
int close(void);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
enum ha_rkey_function find_flag);
@@ -144,7 +144,7 @@ class ha_myisam: public handler
Alter_inplace_info *alter_info);
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
#ifdef HAVE_QUERY_CACHE
- my_bool register_query_cache_table(THD *thd, char *table_key,
+ my_bool register_query_cache_table(THD *thd, const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c
index c0967a60d13..ab45a16a96c 100644
--- a/storage/myisam/mi_create.c
+++ b/storage/myisam/mi_create.c
@@ -47,7 +47,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
uint internal_table= flags & HA_CREATE_INTERNAL_TABLE;
ulong reclength, real_reclength,min_pack_length;
char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr;
- char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr;
+ char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr= 0;
ulong pack_reclength;
ulonglong tot_length,max_rows, tmp;
enum en_fieldtype type;
diff --git a/storage/myisam/mi_unique.c b/storage/myisam/mi_unique.c
index dae453beaec..371c1a7fd6c 100644
--- a/storage/myisam/mi_unique.c
+++ b/storage/myisam/mi_unique.c
@@ -19,7 +19,7 @@
#include "myisamdef.h"
#include <m_ctype.h>
-my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, uchar *record,
+my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, const uchar *record,
ha_checksum unique_hash, my_off_t disk_pos)
{
my_off_t lastpos=info->lastpos;
@@ -27,7 +27,8 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, uchar *record,
uchar *key_buff=info->lastkey2;
DBUG_ENTER("mi_check_unique");
- mi_unique_store(record+key->seg->start, unique_hash);
+ /* We need to store the hash value as a key in the record, breaking const */
+ mi_unique_store(((uchar*) record)+key->seg->start, unique_hash);
_mi_make_key(info,def->key,key_buff,record,0);
/* The above changed info->lastkey2. Inform mi_rnext_same(). */
diff --git a/storage/myisam/mi_update.c b/storage/myisam/mi_update.c
index b75bd4bf2aa..459ce0eade3 100644
--- a/storage/myisam/mi_update.c
+++ b/storage/myisam/mi_update.c
@@ -19,7 +19,8 @@
#include "fulltext.h"
#include "rt_index.h"
-int mi_update(register MI_INFO *info, const uchar *oldrec, uchar *newrec)
+int mi_update(register MI_INFO *info, const uchar *oldrec,
+ const uchar *newrec)
{
int flag,key_changed,save_errno;
reg3 my_off_t pos;
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index ff12cb53dd9..0d718f0a22e 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -696,7 +696,7 @@ extern int mi_indexes_are_disabled(MI_INFO *info);
ulong _mi_calc_total_blob_length(MI_INFO *info, const uchar *record);
ha_checksum mi_checksum(MI_INFO *info, const uchar *buf);
ha_checksum mi_static_checksum(MI_INFO *info, const uchar *buf);
-my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, uchar *record,
+my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, const uchar *record,
ha_checksum unique_hash, my_off_t pos);
ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const uchar *buf);
int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 3d91aa67793..dbcd7a0cb3b 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1104,7 +1104,7 @@ int ha_myisammrg::write_row(uchar * buf)
DBUG_RETURN(myrg_write(file,buf));
}
-int ha_myisammrg::update_row(const uchar * old_data, uchar * new_data)
+int ha_myisammrg::update_row(const uchar * old_data, const uchar * new_data)
{
DBUG_ASSERT(this->file->children_attached);
return myrg_update(file,old_data,new_data);
@@ -1609,7 +1609,7 @@ void ha_myisammrg::append_create_info(String *packet)
for (first= open_table= children_l;;
open_table= open_table->next_global)
{
- LEX_STRING db= { open_table->db, open_table->db_length };
+ LEX_CSTRING db= { open_table->db, open_table->db_length };
if (open_table != first)
packet->append(',');
@@ -1646,7 +1646,7 @@ bool ha_myisammrg::inplace_alter_table(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{
char tmp_path[FN_REFLEN];
- char *name= table->s->normalized_path.str;
+ const char *name= table->s->normalized_path.str;
DBUG_ENTER("ha_myisammrg::inplace_alter_table");
fn_format(tmp_path, name, "", MYRG_NAME_TMPEXT, MY_UNPACK_FILENAME | MY_APPEND_EXT);
int res= create_mrg(tmp_path, ha_alter_info->create_info);
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index b6db549119d..6ace880ab99 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -112,7 +112,7 @@ public:
virtual handler *clone(const char *name, MEM_ROOT *mem_root);
int close(void);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
enum ha_rkey_function find_flag);
diff --git a/storage/myisammrg/myrg_update.c b/storage/myisammrg/myrg_update.c
index add6f9f819b..fd28b2699e9 100644
--- a/storage/myisammrg/myrg_update.c
+++ b/storage/myisammrg/myrg_update.c
@@ -18,7 +18,8 @@
#include "myrg_def.h"
-int myrg_update(register MYRG_INFO *info,const uchar *oldrec, uchar *newrec)
+int myrg_update(register MYRG_INFO *info,const uchar *oldrec,
+ const uchar *newrec)
{
if (!info->current_table)
return (my_errno=HA_ERR_NO_ACTIVE_RECORD);
diff --git a/storage/myisammrg/mysql-test/storage_engine/create_table.rdiff b/storage/myisammrg/mysql-test/storage_engine/create_table.rdiff
index 5f5c2528a95..ad6352d3e7b 100644
--- a/storage/myisammrg/mysql-test/storage_engine/create_table.rdiff
+++ b/storage/myisammrg/mysql-test/storage_engine/create_table.rdiff
@@ -29,14 +29,14 @@
-SHOW CREATE TABLE t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
-- `1` bigint(20) NOT NULL DEFAULT 0
+- `1` int(1) NOT NULL DEFAULT 0
-) ENGINE=<STORAGE_ENGINE> DEFAULT CHARSET=latin1
-SELECT * FROM t1;
-1
-1
-2
-DROP TABLE t1;
-+ERROR HY000: 'test.t1' is not BASE TABLE
++ERROR HY000: 'test.t1' is not of type 'BASE TABLE'
+# ERROR: Statement ended with errno 1347, errname ER_WRONG_OBJECT (expected to succeed)
+# ------------ UNEXPECTED RESULT ------------
+# The statement|command finished with ER_WRONG_OBJECT.
diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc
index 66a20e9a6a1..4b858d468f5 100644
--- a/storage/oqgraph/ha_oqgraph.cc
+++ b/storage/oqgraph/ha_oqgraph.cc
@@ -297,7 +297,7 @@ int ha_oqgraph::oqgraph_check_table_structure (TABLE *table_arg)
Field **field= table_arg->field;
for (i= 0; *field && skel[i].colname; i++, field++) {
- DBUG_PRINT( "oq-debug", ("Column %d: name='%s', expected '%s'; type=%d, expected %d.", i, (*field)->field_name, skel[i].colname, (*field)->type(), skel[i].coltype));
+ DBUG_PRINT( "oq-debug", ("Column %d: name='%s', expected '%s'; type=%d, expected %d.", i, (*field)->field_name.str, skel[i].colname, (*field)->type(), skel[i].coltype));
bool badColumn = false;
bool isLatchColumn = strcmp(skel[i].colname, "latch")==0;
bool isStringLatch = true;
@@ -346,7 +346,7 @@ int ha_oqgraph::oqgraph_check_table_structure (TABLE *table_arg)
push_warning_printf( current_thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, "Column %d must be NULL.", i);
}
/* Check the column name */
- if (!badColumn) if (strcmp(skel[i].colname,(*field)->field_name)) {
+ if (!badColumn) if (strcmp(skel[i].colname,(*field)->field_name.str)) {
badColumn = true;
push_warning_printf( current_thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, "Column %d must be named '%s'.", i, skel[i].colname);
}
@@ -577,11 +577,10 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
size_t tlen= strlen(options->table_name);
size_t plen= (int)(p - name) + tlen + 1;
- share->path.str= (char*)alloc_root(&share->mem_root, plen + 1); // MDEV-5996 space for trailing zero
- // it seems there was a misunderstanding of why there is a separate length field in the String object
- strmov(strnmov(share->path.str, name, (int)(p - name) + 1), options->table_name);
-
- share->path.str[plen] = 0; // MDEV-5996 Make sure the pointer is zero terminated. I really think this needs refactoring, soon...
+ share->path.str= (char*)alloc_root(&share->mem_root, plen + 1);
+ strmov(strnmov((char*) share->path.str, name, (int)(p - name) + 1),
+ options->table_name);
+ DBUG_ASSERT(strlen(share->path.str) == plen);
share->normalized_path.str= share->path.str;
share->path.length= share->normalized_path.length= plen;
@@ -655,7 +654,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
for (Field **field= edges->field; *field; ++field)
{
- if (strcmp(options->origid, (*field)->field_name))
+ if (strcmp(options->origid, (*field)->field_name.str))
continue;
if ((*field)->cmp_type() != INT_RESULT ||
!((*field)->flags & NOT_NULL_FLAG))
@@ -680,7 +679,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
for (Field **field= edges->field; *field; ++field)
{
- if (strcmp(options->destid, (*field)->field_name))
+ if (strcmp(options->destid, (*field)->field_name.str))
continue;
if ((*field)->type() != origid->type() ||
!((*field)->flags & NOT_NULL_FLAG))
@@ -703,7 +702,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
}
// Make sure origid column != destid column
- if (strcmp( origid->field_name, destid->field_name)==0) {
+ if (strcmp( origid->field_name.str, destid->field_name.str)==0) {
fprint_error("Invalid OQGRAPH backing store ('%s.destid' attribute set to same column as origid attribute)", p+1, options->table_name);
closefrm(edges);
free_table_share(share);
@@ -712,7 +711,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
for (Field **field= edges->field; options->weight && *field; ++field)
{
- if (strcmp(options->weight, (*field)->field_name))
+ if (strcmp(options->weight, (*field)->field_name.str))
continue;
if ((*field)->result_type() != REAL_RESULT ||
!((*field)->flags & NOT_NULL_FLAG))
@@ -803,7 +802,7 @@ int ha_oqgraph::write_row(byte * buf)
return HA_ERR_TABLE_READONLY;
}
-int ha_oqgraph::update_row(const byte * old, byte * buf)
+int ha_oqgraph::update_row(const uchar * old, const uchar * buf)
{
return HA_ERR_TABLE_READONLY;
}
diff --git a/storage/oqgraph/ha_oqgraph.h b/storage/oqgraph/ha_oqgraph.h
index 07f47bd1239..f06db8bbf14 100644
--- a/storage/oqgraph/ha_oqgraph.h
+++ b/storage/oqgraph/ha_oqgraph.h
@@ -84,7 +84,7 @@ public:
int open(const char *name, int mode, uint test_if_locked);
int close(void);
int write_row(byte * buf);
- int update_row(const byte * old_data, byte * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const byte * buf);
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
@@ -118,7 +118,7 @@ public:
virtual const char *table_type() const { return hton_name(ht)->str; }
#endif
- my_bool register_query_cache_table(THD *thd, char *table_key,
+ my_bool register_query_cache_table(THD *thd, const char *table_key,
uint key_length,
qc_engine_callback
*engine_callback,
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index 4077e28a51c..7ea68670304 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -286,7 +286,7 @@ void ha_perfschema::use_hidden_primary_key(void)
table->column_bitmaps_set_no_signal(&table->s->all_set, table->write_set);
}
-int ha_perfschema::update_row(const uchar *old_data, uchar *new_data)
+int ha_perfschema::update_row(const uchar *old_data, const uchar *new_data)
{
DBUG_ENTER("ha_perfschema::update_row");
if (!pfs_initialized)
diff --git a/storage/perfschema/ha_perfschema.h b/storage/perfschema/ha_perfschema.h
index ff87b1fd665..988caae2de3 100644
--- a/storage/perfschema/ha_perfschema.h
+++ b/storage/perfschema/ha_perfschema.h
@@ -130,7 +130,7 @@ public:
@param new_data the row new values
@return 0 on success
*/
- int update_row(const uchar *old_data, uchar *new_data);
+ int update_row(const uchar *old_data, const uchar *new_data);
/**
Delete a row.
@@ -188,7 +188,8 @@ public:
{ return HA_CACHE_TBL_NOCACHE; }
virtual my_bool register_query_cache_table
- (THD *, char *, uint , qc_engine_callback *engine_callback, ulonglong *)
+ (THD *, const char *, uint , qc_engine_callback *engine_callback,
+ ulonglong *)
{
*engine_callback= 0;
return FALSE;
diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc
index 3fd0e62ac44..c411025d148 100644
--- a/storage/perfschema/pfs.cc
+++ b/storage/perfschema/pfs.cc
@@ -1236,7 +1236,7 @@ static enum_operation_type socket_operation_map[]=
@param [out] output_length Length of the resulting output string.
@return 0 for success, non zero for errors
*/
-static int build_prefix(const LEX_STRING *prefix, const char *category,
+static int build_prefix(const LEX_CSTRING *prefix, const char *category,
char *output, int *output_length)
{
int len= strlen(category);
diff --git a/storage/perfschema/pfs_column_values.cc b/storage/perfschema/pfs_column_values.cc
index 65d0ae7171b..9c4dee89af5 100644
--- a/storage/perfschema/pfs_column_values.cc
+++ b/storage/perfschema/pfs_column_values.cc
@@ -22,29 +22,29 @@
#include "my_global.h"
#include "pfs_column_values.h"
-LEX_STRING PERFORMANCE_SCHEMA_str=
-{ C_STRING_WITH_LEN("performance_schema") };
+LEX_CSTRING PERFORMANCE_SCHEMA_str=
+{ STRING_WITH_LEN("performance_schema") };
-LEX_STRING mutex_instrument_prefix=
-{ C_STRING_WITH_LEN("wait/synch/mutex/") };
+LEX_CSTRING mutex_instrument_prefix=
+{ STRING_WITH_LEN("wait/synch/mutex/") };
-LEX_STRING rwlock_instrument_prefix=
-{ C_STRING_WITH_LEN("wait/synch/rwlock/") };
+LEX_CSTRING rwlock_instrument_prefix=
+{ STRING_WITH_LEN("wait/synch/rwlock/") };
-LEX_STRING cond_instrument_prefix=
-{ C_STRING_WITH_LEN("wait/synch/cond/") };
+LEX_CSTRING cond_instrument_prefix=
+{ STRING_WITH_LEN("wait/synch/cond/") };
-LEX_STRING thread_instrument_prefix=
-{ C_STRING_WITH_LEN("thread/") };
+LEX_CSTRING thread_instrument_prefix=
+{ STRING_WITH_LEN("thread/") };
-LEX_STRING file_instrument_prefix=
-{ C_STRING_WITH_LEN("wait/io/file/") };
+LEX_CSTRING file_instrument_prefix=
+{ STRING_WITH_LEN("wait/io/file/") };
-LEX_STRING stage_instrument_prefix=
-{ C_STRING_WITH_LEN("stage/") };
+LEX_CSTRING stage_instrument_prefix=
+{ STRING_WITH_LEN("stage/") };
-LEX_STRING statement_instrument_prefix=
-{ C_STRING_WITH_LEN("statement/") };
+LEX_CSTRING statement_instrument_prefix=
+{ STRING_WITH_LEN("statement/") };
-LEX_STRING socket_instrument_prefix=
-{ C_STRING_WITH_LEN("wait/io/socket/") };
+LEX_CSTRING socket_instrument_prefix=
+{ STRING_WITH_LEN("wait/io/socket/") };
diff --git a/storage/perfschema/pfs_column_values.h b/storage/perfschema/pfs_column_values.h
index 204d5230ddf..952230043af 100644
--- a/storage/perfschema/pfs_column_values.h
+++ b/storage/perfschema/pfs_column_values.h
@@ -25,23 +25,23 @@
*/
/** String, "PERFORMANCE_SCHEMA". */
-extern LEX_STRING PERFORMANCE_SCHEMA_str;
+extern LEX_CSTRING PERFORMANCE_SCHEMA_str;
/** String prefix for all mutex instruments. */
-extern LEX_STRING mutex_instrument_prefix;
+extern LEX_CSTRING mutex_instrument_prefix;
/** String prefix for all rwlock instruments. */
-extern LEX_STRING rwlock_instrument_prefix;
+extern LEX_CSTRING rwlock_instrument_prefix;
/** String prefix for all cond instruments. */
-extern LEX_STRING cond_instrument_prefix;
+extern LEX_CSTRING cond_instrument_prefix;
/** String prefix for all thread instruments. */
-extern LEX_STRING thread_instrument_prefix;
+extern LEX_CSTRING thread_instrument_prefix;
/** String prefix for all file instruments. */
-extern LEX_STRING file_instrument_prefix;
+extern LEX_CSTRING file_instrument_prefix;
/** String prefix for all stage instruments. */
-extern LEX_STRING stage_instrument_prefix;
+extern LEX_CSTRING stage_instrument_prefix;
/** String prefix for all statement instruments. */
-extern LEX_STRING statement_instrument_prefix;
-extern LEX_STRING socket_instrument_prefix;
+extern LEX_CSTRING statement_instrument_prefix;
+extern LEX_CSTRING socket_instrument_prefix;
#endif
diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc
index 9e9ab02df46..f3c6edcef59 100644
--- a/storage/perfschema/pfs_engine_table.cc
+++ b/storage/perfschema/pfs_engine_table.cc
@@ -284,7 +284,7 @@ int PFS_engine_table::read_row(TABLE *table,
*/
int PFS_engine_table::update_row(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields)
{
my_bitmap_map *org_bitmap;
@@ -396,7 +396,7 @@ void PFS_engine_table::set_field_enum(Field *f, ulonglong value)
void PFS_engine_table::set_field_timestamp(Field *f, ulonglong value)
{
- DBUG_ASSERT(is_timestamp_type(f->real_type()));
+ DBUG_ASSERT(f->type_handler()->is_timestamp_type());
Field_timestamp *f2= (Field_timestamp*) f;
f2->store_TIME((long)(value / 1000000), (value % 1000000));
}
@@ -428,7 +428,7 @@ PFS_engine_table::get_field_varchar_utf8(Field *f, String *val)
int PFS_engine_table::update_row_values(TABLE *,
const unsigned char *,
- unsigned char *,
+ const unsigned char *,
Field **)
{
return HA_ERR_WRONG_COMMAND;
@@ -1372,7 +1372,7 @@ end:
}
int pfs_discover_table_names(handlerton *hton __attribute__((unused)),
- LEX_STRING *db,
+ LEX_CSTRING *db,
MY_DIR *dir __attribute__((unused)),
handlerton::discovered_list *result)
{
diff --git a/storage/perfschema/pfs_engine_table.h b/storage/perfschema/pfs_engine_table.h
index 2bbf8891420..e12ab36cd61 100644
--- a/storage/perfschema/pfs_engine_table.h
+++ b/storage/perfschema/pfs_engine_table.h
@@ -46,7 +46,7 @@ public:
int read_row(TABLE *table, unsigned char *buf, Field **fields);
int update_row(TABLE *table, const unsigned char *old_buf,
- unsigned char *new_buf, Field **fields);
+ const unsigned char *new_buf, Field **fields);
/**
Delete a row from this table.
@@ -165,7 +165,7 @@ protected:
@param fields Table fields
*/
virtual int update_row_values(TABLE *table, const unsigned char *old_buf,
- unsigned char *new_buf, Field **fields);
+ const unsigned char *new_buf, Field **fields);
/**
Delete a row.
@@ -457,7 +457,7 @@ struct PFS_triple_index
bool pfs_show_status(handlerton *hton, THD *thd,
stat_print_fn *print, enum ha_stat_type stat);
-int pfs_discover_table_names(handlerton *hton, LEX_STRING *db,
+int pfs_discover_table_names(handlerton *hton, LEX_CSTRING *db,
MY_DIR *dir,
handlerton::discovered_list *result);
diff --git a/storage/perfschema/table_setup_actors.cc b/storage/perfschema/table_setup_actors.cc
index c82d67fba2d..bf6006057df 100644
--- a/storage/perfschema/table_setup_actors.cc
+++ b/storage/perfschema/table_setup_actors.cc
@@ -217,7 +217,7 @@ int table_setup_actors::read_row_values(TABLE *table,
int table_setup_actors::update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields)
{
Field *f;
diff --git a/storage/perfschema/table_setup_actors.h b/storage/perfschema/table_setup_actors.h
index 2a9395dfac7..66379593cc5 100644
--- a/storage/perfschema/table_setup_actors.h
+++ b/storage/perfschema/table_setup_actors.h
@@ -71,7 +71,7 @@ protected:
virtual int update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields);
virtual int delete_row_values(TABLE *table,
diff --git a/storage/perfschema/table_setup_consumers.cc b/storage/perfschema/table_setup_consumers.cc
index c09853ffeca..f3529eb8846 100644
--- a/storage/perfschema/table_setup_consumers.cc
+++ b/storage/perfschema/table_setup_consumers.cc
@@ -190,7 +190,7 @@ int table_setup_consumers::read_row_values(TABLE *table,
int table_setup_consumers::update_row_values(TABLE *table,
const unsigned char *,
- unsigned char *,
+ const unsigned char *,
Field **fields)
{
Field *f;
diff --git a/storage/perfschema/table_setup_consumers.h b/storage/perfschema/table_setup_consumers.h
index e59033c0ad1..f5a386829a1 100644
--- a/storage/perfschema/table_setup_consumers.h
+++ b/storage/perfschema/table_setup_consumers.h
@@ -60,7 +60,7 @@ protected:
virtual int update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields);
table_setup_consumers();
diff --git a/storage/perfschema/table_setup_instruments.cc b/storage/perfschema/table_setup_instruments.cc
index d911128ce94..f5ac1cafe63 100644
--- a/storage/perfschema/table_setup_instruments.cc
+++ b/storage/perfschema/table_setup_instruments.cc
@@ -217,7 +217,7 @@ int table_setup_instruments::read_row_values(TABLE *table,
int table_setup_instruments::update_row_values(TABLE *table,
const unsigned char *,
- unsigned char *,
+ const unsigned char *,
Field **fields)
{
Field *f;
diff --git a/storage/perfschema/table_setup_instruments.h b/storage/perfschema/table_setup_instruments.h
index 2e70a528bbd..dfe9070721b 100644
--- a/storage/perfschema/table_setup_instruments.h
+++ b/storage/perfschema/table_setup_instruments.h
@@ -92,7 +92,7 @@ protected:
virtual int update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields);
table_setup_instruments();
diff --git a/storage/perfschema/table_setup_objects.cc b/storage/perfschema/table_setup_objects.cc
index 5321271a62d..994622f4a52 100644
--- a/storage/perfschema/table_setup_objects.cc
+++ b/storage/perfschema/table_setup_objects.cc
@@ -265,7 +265,7 @@ int table_setup_objects::read_row_values(TABLE *table,
int table_setup_objects::update_row_values(TABLE *table,
const unsigned char *,
- unsigned char *,
+ const unsigned char *,
Field **fields)
{
int result;
diff --git a/storage/perfschema/table_setup_objects.h b/storage/perfschema/table_setup_objects.h
index 55423ffd90f..7fcefa45407 100644
--- a/storage/perfschema/table_setup_objects.h
+++ b/storage/perfschema/table_setup_objects.h
@@ -74,7 +74,7 @@ protected:
virtual int update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields);
virtual int delete_row_values(TABLE *table,
diff --git a/storage/perfschema/table_setup_timers.cc b/storage/perfschema/table_setup_timers.cc
index 911fa121e06..9c6af49595d 100644
--- a/storage/perfschema/table_setup_timers.cc
+++ b/storage/perfschema/table_setup_timers.cc
@@ -145,7 +145,7 @@ int table_setup_timers::read_row_values(TABLE *table,
int table_setup_timers::update_row_values(TABLE *table,
const unsigned char *,
- unsigned char *,
+ const unsigned char *,
Field **fields)
{
Field *f;
diff --git a/storage/perfschema/table_setup_timers.h b/storage/perfschema/table_setup_timers.h
index 46af68bb9e3..f230a68af98 100644
--- a/storage/perfschema/table_setup_timers.h
+++ b/storage/perfschema/table_setup_timers.h
@@ -58,7 +58,7 @@ protected:
virtual int update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields);
table_setup_timers();
diff --git a/storage/perfschema/table_threads.cc b/storage/perfschema/table_threads.cc
index 5c78b567b8c..7be51b2bb20 100644
--- a/storage/perfschema/table_threads.cc
+++ b/storage/perfschema/table_threads.cc
@@ -292,7 +292,7 @@ int table_threads::read_row_values(TABLE *table,
int table_threads::update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields)
{
Field *f;
diff --git a/storage/perfschema/table_threads.h b/storage/perfschema/table_threads.h
index 10afbe14e74..fb843f5ca36 100644
--- a/storage/perfschema/table_threads.h
+++ b/storage/perfschema/table_threads.h
@@ -87,7 +87,7 @@ protected:
virtual int update_row_values(TABLE *table,
const unsigned char *old_buf,
- unsigned char *new_buf,
+ const unsigned char *new_buf,
Field **fields);
protected:
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index 245cc437084..03d1a2df58d 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -4985,7 +4985,7 @@ int ha_rocksdb::create_cfs(
ER_UNKNOWN_ERROR, "Unsupported collation on string indexed "
"column %s.%s Use binary collation (%s).",
MYF(0), tbl_def_arg->full_tablename().c_str(),
- table_arg->key_info[i].key_part[part].field->field_name,
+ table_arg->key_info[i].key_part[part].field->field_name.str,
collation_err.c_str());
DBUG_RETURN(HA_EXIT_FAILURE);
}
@@ -5189,8 +5189,8 @@ int ha_rocksdb::compare_key_parts(const KEY *const old_key,
/* Check to see that key parts themselves match */
for (uint i = 0; i < old_key->user_defined_key_parts; i++) {
- if (strcmp(old_key->key_part[i].field->field_name,
- new_key->key_part[i].field->field_name) != 0) {
+ if (strcmp(old_key->key_part[i].field->field_name.str,
+ new_key->key_part[i].field->field_name.str) != 0) {
DBUG_RETURN(HA_EXIT_FAILURE);
}
}
@@ -8311,7 +8311,8 @@ void ha_rocksdb::calc_updated_indexes() {
}
}
-int ha_rocksdb::update_row(const uchar *const old_data, uchar *const new_data) {
+int ha_rocksdb::update_row(const uchar *const old_data,
+ const uchar *const new_data) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(old_data != nullptr);
diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h
index 5852ad4e954..27885d50eb5 100644
--- a/storage/rocksdb/ha_rocksdb.h
+++ b/storage/rocksdb/ha_rocksdb.h
@@ -887,7 +887,7 @@ public:
int write_row(uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
- int update_row(const uchar *const old_data, uchar *const new_data) override
+ int update_row(const uchar *const old_data, const uchar *const new_data) override
MY_ATTRIBUTE((__warn_unused_result__));
int delete_row(const uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
@@ -1139,7 +1139,7 @@ public:
enum thr_lock_type lock_type) override
MY_ATTRIBUTE((__warn_unused_result__));
- my_bool register_query_cache_table(THD *const thd, char *const table_key,
+ my_bool register_query_cache_table(THD *const thd, const char *table_key,
uint key_length,
qc_engine_callback *const engine_callback,
ulonglong *const engine_data) override {
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result b/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result
index d1e445f734c..37797c7a8da 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/tbl_opt_data_index_dir.result
@@ -3,14 +3,14 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb DATA DIRECTORY = '
ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options")
show warnings;
Level Code Message
-Warning 1296 Got error 198 'Specifying DATA DIRECTORY for an individual table is not supported.' from ROCKSDB
+Warning 1296 Got error 200 'Specifying DATA DIRECTORY for an individual table is not supported.' from ROCKSDB
Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options")
Warning 1030 Got error 140 "Wrong create options" from storage engine ROCKSDB
CREATE TABLE t1 (a INT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb INDEX DIRECTORY = '/foo/bar/index';
ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options")
show warnings;
Level Code Message
-Warning 1296 Got error 199 'Specifying INDEX DIRECTORY for an individual table is not supported.' from ROCKSDB
+Warning 1296 Got error 201 'Specifying INDEX DIRECTORY for an individual table is not supported.' from ROCKSDB
Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options")
Warning 1030 Got error 140 "Wrong create options" from storage engine ROCKSDB
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=rocksdb PARTITION BY RANGE (id)
diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc
index da4eead99b8..2bfb6f9be7c 100644
--- a/storage/rocksdb/rdb_datadic.cc
+++ b/storage/rocksdb/rdb_datadic.cc
@@ -2833,16 +2833,16 @@ bool Rdb_validate_tbls::check_frm_file(const std::string &fullpath,
the connection handle as we don't have one here.
*/
char eng_type_buf[NAME_CHAR_LEN+1];
- LEX_STRING eng_type_str = {eng_type_buf, 0};
- //enum legacy_db_type eng_type;
- frm_type_enum type = dd_frm_type(nullptr, fullfilename.c_ptr(), &eng_type_str);
- if (type == FRMTYPE_ERROR) {
+ LEX_CSTRING eng_type_str = {eng_type_buf, 0};
+ bool is_sequence;
+ enum Table_type type = dd_frm_type(nullptr, fullfilename.c_ptr(), &eng_type_str, &is_sequence);
+ if (type == TABLE_TYPE_UNKNOWN) {
sql_print_warning("RocksDB: Failed to open/read .from file: %s",
fullfilename.ptr());
return false;
}
- if (type == FRMTYPE_TABLE) {
+ if (type == TABLE_TYPE_NORMAL) {
/* For a RocksDB table do we have a reference in the data dictionary? */
if (!strncmp(eng_type_str.str, "ROCKSDB", eng_type_str.length)) {
/*
diff --git a/storage/sequence/sequence.cc b/storage/sequence/sequence.cc
index 599374c6f8c..3e56303973d 100644
--- a/storage/sequence/sequence.cc
+++ b/storage/sequence/sequence.cc
@@ -29,7 +29,7 @@
#include <table.h>
#include <field.h>
-handlerton *sequence_hton;
+static handlerton *sequence_hton;
class Sequence_share : public Handler_share {
public:
@@ -418,7 +418,7 @@ create_group_by_handler(THD *thd, Query *query)
if (field->table != query->from->table)
return 0;
/* Check that we are using a SUM() on the primary key */
- if (strcmp(field->field_name, "seq"))
+ if (strcmp(field->field_name.str, "seq"))
return 0;
}
diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc
index 650bc93cf67..be57c04806b 100644
--- a/storage/sphinx/ha_sphinx.cc
+++ b/storage/sphinx/ha_sphinx.cc
@@ -1031,7 +1031,7 @@ static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
for ( int i=0; i<share->m_iTableFields; i++ )
{
- share->m_sTableField[i] = sphDup ( table->field[i]->field_name );
+ share->m_sTableField[i] = sphDup ( table->field[i]->field_name.str );
share->m_eTableFieldType[i] = table->field[i]->type();
}
}
@@ -2334,7 +2334,7 @@ int ha_sphinx::write_row ( byte * )
for ( Field ** ppField = table->field; *ppField; ppField++ )
{
- sQuery.append ( (*ppField)->field_name );
+ sQuery.append ( (*ppField)->field_name.str );
if ( ppField[1] )
sQuery.append ( ", " );
}
@@ -2460,7 +2460,7 @@ int ha_sphinx::delete_row ( const byte * )
}
-int ha_sphinx::update_row ( const byte *, byte * )
+int ha_sphinx::update_row ( const byte *, const byte * )
{
SPH_ENTER_METHOD();
SPH_RET ( HA_ERR_WRONG_COMMAND );
@@ -3430,7 +3430,7 @@ int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
if ( eType!=MYSQL_TYPE_TIMESTAMP && !IsIntegerFieldType(eType) && eType!=MYSQL_TYPE_VARCHAR && eType!=MYSQL_TYPE_FLOAT )
{
my_snprintf ( sError, sizeof(sError), "%s: %dth column (attribute %s) MUST be integer, bigint, timestamp, varchar, or float",
- name, i+1, table->field[i]->field_name );
+ name, i+1, table->field[i]->field_name.str );
break;
}
}
@@ -3442,10 +3442,10 @@ int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
if (
table->s->keys!=1 ||
table->key_info[0].user_defined_key_parts!=1 ||
- strcasecmp ( table->key_info[0].key_part[0].field->field_name, table->field[2]->field_name ) )
+ strcasecmp ( table->key_info[0].key_part[0].field->field_name.str, table->field[2]->field_name.str ) )
{
my_snprintf ( sError, sizeof(sError), "%s: there must be an index on '%s' column",
- name, table->field[2]->field_name );
+ name, table->field[2]->field_name.str );
break;
}
@@ -3460,7 +3460,7 @@ int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
sError[0] = '\0';
// check that 1st column is id, is of int type, and has an index
- if ( strcmp ( table->field[0]->field_name, "id" ) )
+ if ( strcmp ( table->field[0]->field_name.str, "id" ) )
{
my_snprintf ( sError, sizeof(sError), "%s: 1st column must be called 'id'", name );
break;
@@ -3476,7 +3476,7 @@ int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
if (
table->s->keys!=1 ||
table->key_info[0].user_defined_key_parts!=1 ||
- strcasecmp ( table->key_info[0].key_part[0].field->field_name, "id" ) )
+ strcasecmp ( table->key_info[0].key_part[0].field->field_name.str, "id" ) )
{
my_snprintf ( sError, sizeof(sError), "%s: 'id' column must be indexed", name );
break;
@@ -3489,7 +3489,7 @@ int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
if ( eType!=MYSQL_TYPE_TIMESTAMP && !IsIntegerFieldType(eType) && eType!=MYSQL_TYPE_VARCHAR && eType!=MYSQL_TYPE_FLOAT )
{
my_snprintf ( sError, sizeof(sError), "%s: column %d(%s) is of unsupported type (use int/bigint/timestamp/varchar/float)",
- name, i+1, table->field[i]->field_name );
+ name, i+1, table->field[i]->field_name.str );
break;
}
}
diff --git a/storage/sphinx/ha_sphinx.h b/storage/sphinx/ha_sphinx.h
index c310deb7060..8e6af908aab 100644
--- a/storage/sphinx/ha_sphinx.h
+++ b/storage/sphinx/ha_sphinx.h
@@ -86,7 +86,7 @@ public:
int close ();
int write_row ( byte * buf );
- int update_row ( const byte * old_data, byte * new_data );
+ int update_row ( const byte * old_data, const byte * new_data );
int delete_row ( const byte * buf );
int extra ( enum ha_extra_function op );
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index d6a5a20df8f..7ed8661cc74 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -7795,7 +7795,8 @@ int ha_spider::cmp_ref(
) {
if ((ret = (*field)->cmp_binary_offset(ptr_diff)))
{
- DBUG_PRINT("info",("spider different at %s", (*field)->field_name));
+ DBUG_PRINT("info",("spider different at %s",
+ (*field)->field_name.str));
break;
}
}
@@ -9752,7 +9753,7 @@ void ha_spider::end_bulk_update(
int ha_spider::bulk_update_row(
const uchar *old_data,
- uchar *new_data,
+ const uchar *new_data,
uint *dup_key_found
) {
DBUG_ENTER("ha_spider::bulk_update_row");
@@ -9763,7 +9764,7 @@ int ha_spider::bulk_update_row(
int ha_spider::update_row(
const uchar *old_data,
- uchar *new_data
+ const uchar *new_data
) {
int error_num;
THD *thd = ha_thd();
@@ -9995,7 +9996,7 @@ int ha_spider::pre_direct_update_rows_init(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
- uchar *new_data
+ const uchar *new_data
) {
int error_num;
DBUG_ENTER("ha_spider::pre_direct_update_rows_init");
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index acc75ed1c05..87c6afaa89f 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -569,12 +569,12 @@ public:
void end_bulk_update();
int bulk_update_row(
const uchar *old_data,
- uchar *new_data,
+ const uchar *new_data,
uint *dup_key_found
);
int update_row(
const uchar *old_data,
- uchar *new_data
+ const uchar *new_data
);
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
int direct_update_rows_init(
@@ -582,7 +582,7 @@ public:
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
- uchar *new_data
+ const uchar *new_data
);
#ifdef HA_CAN_BULK_ACCESS
int pre_direct_update_rows_init(
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index bb5711de007..ce425e9a65e 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -1665,7 +1665,7 @@ int spider_db_append_key_where_internal(
if (sql_kind == SPIDER_SQL_KIND_HANDLER)
{
- char *key_name = key_info->name;
+ const char *key_name = key_info->name;
key_name_length = strlen(key_name);
if (str->reserve(SPIDER_SQL_READ_LEN +
/* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + key_name_length))
@@ -2844,7 +2844,7 @@ int spider_db_fetch_row(
) {
int error_num;
DBUG_ENTER("spider_db_fetch_row");
- DBUG_PRINT("info", ("spider field_name %s", field->field_name));
+ DBUG_PRINT("info", ("spider field_name %s", field->field_name.str));
DBUG_PRINT("info", ("spider fieldcharset %s", field->charset()->csname));
field->move_field_offset(ptr_diff);
error_num = row->store_to_field(field, share->access_charset);
@@ -2967,7 +2967,8 @@ int spider_db_fetch_table(
my_bitmap_map *tmp_map =
dbug_tmp_use_all_columns(table, table->write_set);
#endif
- DBUG_PRINT("info", ("spider bitmap is set %s", (*field)->field_name));
+ DBUG_PRINT("info", ("spider bitmap is set %s",
+ (*field)->field_name.str));
if ((error_num =
spider_db_fetch_row(share, *field, row, ptr_diff)))
DBUG_RETURN(error_num);
@@ -3138,7 +3139,7 @@ int spider_db_fetch_key(
my_bitmap_map *tmp_map =
dbug_tmp_use_all_columns(table, table->write_set);
#endif
- DBUG_PRINT("info", ("spider bitmap is set %s", field->field_name));
+ DBUG_PRINT("info", ("spider bitmap is set %s", field->field_name.str));
if ((error_num =
spider_db_fetch_row(share, field, row, ptr_diff)))
DBUG_RETURN(error_num);
@@ -3252,7 +3253,8 @@ int spider_db_fetch_minimum_columns(
my_bitmap_map *tmp_map =
dbug_tmp_use_all_columns(table, table->write_set);
#endif
- DBUG_PRINT("info", ("spider bitmap is set %s", (*field)->field_name));
+ DBUG_PRINT("info", ("spider bitmap is set %s",
+ (*field)->field_name.str));
if ((error_num = spider_db_fetch_row(share, *field, row, ptr_diff)))
DBUG_RETURN(error_num);
#ifndef DBUG_OFF
@@ -5114,7 +5116,8 @@ int spider_db_seek_tmp_table(
my_bitmap_map *tmp_map =
dbug_tmp_use_all_columns(table, table->write_set);
#endif
- DBUG_PRINT("info", ("spider bitmap is set %s", (*field)->field_name));
+ DBUG_PRINT("info", ("spider bitmap is set %s",
+ (*field)->field_name.str));
if ((error_num =
spider_db_fetch_row(spider->share, *field, row, ptr_diff)))
DBUG_RETURN(error_num);
@@ -5201,7 +5204,7 @@ int spider_db_seek_tmp_key(
my_bitmap_map *tmp_map =
dbug_tmp_use_all_columns(table, table->write_set);
#endif
- DBUG_PRINT("info", ("spider bitmap is set %s", field->field_name));
+ DBUG_PRINT("info", ("spider bitmap is set %s", field->field_name.str));
if ((error_num =
spider_db_fetch_row(spider->share, field, row, ptr_diff)))
DBUG_RETURN(error_num);
@@ -5291,7 +5294,8 @@ int spider_db_seek_tmp_minimum_columns(
my_bitmap_map *tmp_map =
dbug_tmp_use_all_columns(table, table->write_set);
#endif
- DBUG_PRINT("info", ("spider bitmap is set %s", (*field)->field_name));
+ DBUG_PRINT("info", ("spider bitmap is set %s",
+ (*field)->field_name.str));
if ((error_num =
spider_db_fetch_row(spider->share, *field, row, ptr_diff)))
DBUG_RETURN(error_num);
@@ -5303,7 +5307,7 @@ int spider_db_seek_tmp_minimum_columns(
else if (bitmap_is_set(table->read_set, (*field)->field_index))
{
DBUG_PRINT("info", ("spider bitmap is cleared %s",
- (*field)->field_name));
+ (*field)->field_name.str));
bitmap_clear_bit(table->read_set, (*field)->field_index);
}
}
@@ -8059,10 +8063,7 @@ int spider_db_open_item_ident(
}
if (str)
{
- if (item_ident->field_name)
- field_name_length = strlen(item_ident->field_name);
- else
- field_name_length = 0;
+ field_name_length = item_ident->field_name.length;
if (share->access_charset->cset == system_charset_info->cset)
{
if (str->reserve(alias_length +
@@ -8072,7 +8073,7 @@ int spider_db_open_item_ident(
}
str->q_append(alias, alias_length);
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name(str, item_ident->field_name, field_name_length)))
+ append_name(str, item_ident->field_name.str, field_name_length)))
{
DBUG_RETURN(error_num);
}
@@ -8081,7 +8082,7 @@ int spider_db_open_item_ident(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(alias, alias_length);
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name_with_charset(str, item_ident->field_name,
+ append_name_with_charset(str, item_ident->field_name.str,
field_name_length, system_charset_info)))
{
DBUG_RETURN(error_num);
@@ -8140,18 +8141,18 @@ int spider_db_open_item_ref(
(*(item_ref->ref))->type() != Item::CACHE_ITEM &&
item_ref->ref_type() != Item_ref::VIEW_REF &&
!item_ref->table_name &&
- item_ref->name &&
+ item_ref->name.str &&
item_ref->alias_name_used
) {
if (str)
{
- uint length = strlen(item_ref->name);
+ uint length = item_ref->name.length;
if (str->reserve(length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2))
{
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name(str, item_ref->name, length)))
+ append_name(str, item_ref->name.str, length)))
{
DBUG_RETURN(error_num);
}
@@ -9621,7 +9622,7 @@ int spider_db_udf_copy_key_row(
int error_num;
DBUG_ENTER("spider_db_udf_copy_key_row");
if ((error_num = spider_db_append_name_with_quote_str(str,
- (char *) field->field_name, dbton_id)))
+ (char *) field->field_name.str, dbton_id)))
DBUG_RETURN(error_num);
if (str->reserve(joint_length + *length + SPIDER_SQL_AND_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc
index 32acb8df6fb..51b1d1f1752 100644
--- a/storage/spider/spd_db_handlersocket.cc
+++ b/storage/spider/spd_db_handlersocket.cc
@@ -3904,7 +3904,7 @@ int spider_handlersocket_share::create_column_name_str()
str->init_calc_mem(202);
str->set_charset(spider_share->access_charset);
if ((error_num = spider_db_append_name_with_quote_str(str,
- (char *) (*field)->field_name, dbton_id)))
+ (char *) (*field)->field_name.str, dbton_id)))
goto error;
}
DBUG_RETURN(0);
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 9974b6b0628..385b122c274 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -2707,7 +2707,7 @@ void spider_db_mysql::set_dup_key_idx(
uint roop_count, pk_idx = table->s->primary_key;
int key_name_length;
int max_length = 0;
- char *key_name;
+ const char *key_name;
DBUG_ENTER("spider_db_mysql::set_dup_key_idx");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_PRINT("info",("spider error_str=%s", conn->error_str));
@@ -4560,7 +4560,7 @@ int spider_mysql_share::create_column_name_str()
str->init_calc_mem(89);
str->set_charset(spider_share->access_charset);
if ((error_num = spider_db_append_name_with_quote_str(str,
- (char *) (*field)->field_name, dbton_id)))
+ (char *) (*field)->field_name.str, dbton_id)))
goto error;
}
DBUG_RETURN(0);
@@ -11941,7 +11941,7 @@ int spider_mysql_copy_table::append_table_columns(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) (*field)->field_name, spider_dbton_mysql.dbton_id)))
+ (char *) (*field)->field_name.str, spider_dbton_mysql.dbton_id)))
DBUG_RETURN(error_num);
if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_COMMA_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -12070,7 +12070,7 @@ int spider_mysql_copy_table::append_key_order_str(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) field->field_name, spider_dbton_mysql.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_mysql.dbton_id)))
DBUG_RETURN(error_num);
if (key_part->key_part_flag & HA_REVERSE_SORT)
{
@@ -12100,7 +12100,7 @@ int spider_mysql_copy_table::append_key_order_str(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) field->field_name, spider_dbton_mysql.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_mysql.dbton_id)))
DBUG_RETURN(error_num);
if (key_part->key_part_flag & HA_REVERSE_SORT)
{
@@ -12232,7 +12232,7 @@ int spider_mysql_copy_table::copy_key_row(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) field->field_name, spider_dbton_mysql.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_mysql.dbton_id)))
DBUG_RETURN(error_num);
if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + joint_length + *length +
SPIDER_SQL_AND_LEN))
diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc
index 94f354e0a0f..5b322b9c4d7 100644
--- a/storage/spider/spd_db_oracle.cc
+++ b/storage/spider/spd_db_oracle.cc
@@ -4361,7 +4361,7 @@ int spider_oracle_share::create_column_name_str()
str->init_calc_mem(196);
str->set_charset(spider_share->access_charset);
if ((error_num = spider_db_append_name_with_quote_str(str,
- (char *) (*field)->field_name, dbton_id)))
+ (char *) (*field)->field_name.str, dbton_id)))
goto error;
}
DBUG_RETURN(0);
@@ -12090,7 +12090,7 @@ int spider_oracle_copy_table::append_table_columns(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) (*field)->field_name, spider_dbton_oracle.dbton_id)))
+ (char *) (*field)->field_name.str, spider_dbton_oracle.dbton_id)))
DBUG_RETURN(error_num);
if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_COMMA_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -12236,7 +12236,7 @@ int spider_oracle_copy_table::append_key_order_str(
sql_part.q_append(SPIDER_SQL_NAME_QUOTE_STR,
SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql_part,
- (char *) field->field_name, spider_dbton_oracle.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_oracle.dbton_id)))
DBUG_RETURN(error_num);
if (key_part->key_part_flag & HA_REVERSE_SORT)
{
@@ -12270,7 +12270,7 @@ int spider_oracle_copy_table::append_key_order_str(
sql_part.q_append(SPIDER_SQL_NAME_QUOTE_STR,
SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql_part,
- (char *) field->field_name, spider_dbton_oracle.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_oracle.dbton_id)))
DBUG_RETURN(error_num);
if (key_part->key_part_flag & HA_REVERSE_SORT)
{
@@ -12334,7 +12334,7 @@ int spider_oracle_copy_table::append_key_order_str(
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR,
SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) field->field_name, spider_dbton_oracle.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_oracle.dbton_id)))
DBUG_RETURN(error_num);
if (key_part->key_part_flag & HA_REVERSE_SORT)
{
@@ -12367,7 +12367,7 @@ int spider_oracle_copy_table::append_key_order_str(
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR,
SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) field->field_name, spider_dbton_oracle.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_oracle.dbton_id)))
DBUG_RETURN(error_num);
if (key_part->key_part_flag & HA_REVERSE_SORT)
{
@@ -12575,7 +12575,7 @@ int spider_oracle_copy_table::copy_key_row(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
if ((error_num = spider_db_append_name_with_quote_str(&sql,
- (char *) field->field_name, spider_dbton_oracle.dbton_id)))
+ (char *) field->field_name.str, spider_dbton_oracle.dbton_id)))
DBUG_RETURN(error_num);
if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + joint_length + *length +
SPIDER_SQL_AND_LEN))
diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc
index e1e81394ce8..a140fba7915 100644
--- a/storage/spider/spd_sys_table.cc
+++ b/storage/spider/spd_sys_table.cc
@@ -2386,10 +2386,11 @@ TABLE *spider_mk_sys_tmp_table(
Item_field *i_field;
List<Item> i_list;
TABLE *tmp_table;
+ LEX_CSTRING name= { field_name, strlen(field_name) };
DBUG_ENTER("spider_mk_sys_tmp_table");
if (!(field = new Field_blob(
- 4294967295U, FALSE, field_name, cs, TRUE)))
+ 4294967295U, FALSE, &name, cs, TRUE)))
goto error_alloc_field;
field->init(table);
@@ -2444,10 +2445,13 @@ TABLE *spider_mk_sys_tmp_table_for_result(
Item_field *i_field1, *i_field2, *i_field3;
List<Item> i_list;
TABLE *tmp_table;
+ LEX_CSTRING name1= { field_name1, strlen(field_name1) };
+ LEX_CSTRING name2= { field_name2, strlen(field_name2) };
+ LEX_CSTRING name3= { field_name3, strlen(field_name3) };
DBUG_ENTER("spider_mk_sys_tmp_table_for_result");
if (!(field1 = new Field_blob(
- 4294967295U, FALSE, field_name1, cs, TRUE)))
+ 4294967295U, FALSE, &name1, cs, TRUE)))
goto error_alloc_field1;
field1->init(table);
@@ -2463,7 +2467,7 @@ TABLE *spider_mk_sys_tmp_table_for_result(
goto error_push_item1;
if (!(field2 = new (thd->mem_root) Field_blob(
- 4294967295U, FALSE, field_name2, cs, TRUE)))
+ 4294967295U, FALSE, &name2, cs, TRUE)))
goto error_alloc_field2;
field2->init(table);
@@ -2479,7 +2483,7 @@ TABLE *spider_mk_sys_tmp_table_for_result(
goto error_push_item2;
if (!(field3 = new (thd->mem_root) Field_blob(
- 4294967295U, FALSE, field_name3, cs, TRUE)))
+ 4294967295U, FALSE, &name3, cs, TRUE)))
goto error_alloc_field3;
field3->init(table);
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index 513a5fccac0..1a7c42e970f 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -3604,7 +3604,7 @@ cleanup:
return error;
}
-int ha_tokudb::is_val_unique(bool* is_unique, uchar* record, KEY* key_info, uint dict_index, DB_TXN* txn) {
+int ha_tokudb::is_val_unique(bool* is_unique, const uchar* record, KEY* key_info, uint dict_index, DB_TXN* txn) {
int error = 0;
bool has_null;
DBC* tmp_cursor = NULL;
@@ -4160,7 +4160,7 @@ bool ha_tokudb::key_changed(uint keynr, const uchar * old_row, const uchar * new
// 0 on success
// error otherwise
//
-int ha_tokudb::update_row(const uchar * old_row, uchar * new_row) {
+int ha_tokudb::update_row(const uchar * old_row, const uchar * new_row) {
TOKUDB_HANDLER_DBUG_ENTER("");
DBT prim_key, old_prim_key, prim_row, old_prim_row;
int UNINIT_VAR(error);
@@ -6822,7 +6822,7 @@ void ha_tokudb::update_create_info(HA_CREATE_INFO* create_info) {
// during drop table, we do not attempt to remove already dropped
// indexes because we did not keep status.tokudb in sync with list of indexes.
//
-int ha_tokudb::remove_key_name_from_status(DB* status_block, char* key_name, DB_TXN* txn) {
+int ha_tokudb::remove_key_name_from_status(DB* status_block, const char* key_name, DB_TXN* txn) {
int error;
uchar status_key_info[FN_REFLEN + sizeof(HA_METADATA_KEY)];
HA_METADATA_KEY md_key = hatoku_key_name;
@@ -6848,7 +6848,8 @@ int ha_tokudb::remove_key_name_from_status(DB* status_block, char* key_name, DB_
// writes the key name in status.tokudb, so that we may later delete or rename
// the dictionary associated with key_name
//
-int ha_tokudb::write_key_name_to_status(DB* status_block, char* key_name, DB_TXN* txn) {
+int ha_tokudb::write_key_name_to_status(DB* status_block, const char* key_name,
+ DB_TXN* txn) {
int error;
uchar status_key_info[FN_REFLEN + sizeof(HA_METADATA_KEY)];
HA_METADATA_KEY md_key = hatoku_key_name;
@@ -6887,7 +6888,7 @@ void ha_tokudb::trace_create_table_info(const char *name, TABLE * form) {
TOKUDB_HANDLER_TRACE(
"field:%d:%s:type=%d:flags=%x",
i,
- field->field_name,
+ field->field_name.str,
field->type(),
field->flags);
}
@@ -6907,7 +6908,7 @@ void ha_tokudb::trace_create_table_info(const char *name, TABLE * form) {
i,
p,
key_part->length,
- field->field_name,
+ field->field_name.str,
field->type(),
field->flags);
}
@@ -7239,7 +7240,7 @@ int ha_tokudb::create(
"This is probably due to an alter table engine=TokuDB. To load this "
"table, do a dump and load",
name,
- field->field_name
+ field->field_name.str
);
error = HA_ERR_UNSUPPORTED;
goto cleanup;
diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h
index 4a7e395d0d1..7db00339b87 100644
--- a/storage/tokudb/ha_tokudb.h
+++ b/storage/tokudb/ha_tokudb.h
@@ -681,8 +681,8 @@ private:
int remove_metadata(DB* db, void* key_data, uint key_size, DB_TXN* transaction);
int update_max_auto_inc(DB* db, ulonglong val);
- int remove_key_name_from_status(DB* status_block, char* key_name, DB_TXN* txn);
- int write_key_name_to_status(DB* status_block, char* key_name, DB_TXN* txn);
+ int remove_key_name_from_status(DB* status_block, const char* key_name, DB_TXN* txn);
+ int write_key_name_to_status(DB* status_block, const char* key_name, DB_TXN* txn);
int write_auto_inc_create(DB* db, ulonglong val, DB_TXN* txn);
void init_auto_increment();
bool can_replace_into_be_fast(TABLE_SHARE* table_share, KEY_AND_COL_INFO* kc_info, uint pk);
@@ -708,7 +708,7 @@ private:
int create_main_dictionary(const char* name, TABLE* form, DB_TXN* txn, KEY_AND_COL_INFO* kc_info, toku_compression_method compression_method);
void trace_create_table_info(const char *name, TABLE * form);
int is_index_unique(bool* is_unique, DB_TXN* txn, DB* db, KEY* key_info, int lock_flags);
- int is_val_unique(bool* is_unique, uchar* record, KEY* key_info, uint dict_index, DB_TXN* txn);
+ int is_val_unique(bool* is_unique, const uchar* record, KEY* key_info, uint dict_index, DB_TXN* txn);
int do_uniqueness_checks(uchar* record, DB_TXN* txn, THD* thd);
void set_main_dict_put_flags(THD* thd, bool opt_eligible, uint32_t* put_flags);
int insert_row_to_main_dictionary(uchar* record, DBT* pk_key, DBT* pk_val, DB_TXN* txn);
@@ -792,7 +792,7 @@ public:
int optimize(THD * thd, HA_CHECK_OPT * check_opt);
int analyze(THD * thd, HA_CHECK_OPT * check_opt);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
#if MYSQL_VERSION_ID >= 100000
void start_bulk_insert(ha_rows rows, uint flags);
diff --git a/storage/tokudb/ha_tokudb_alter_56.cc b/storage/tokudb/ha_tokudb_alter_56.cc
index ba1afbf091a..b4eccf17b57 100644
--- a/storage/tokudb/ha_tokudb_alter_56.cc
+++ b/storage/tokudb/ha_tokudb_alter_56.cc
@@ -113,7 +113,7 @@ void ha_tokudb::print_alter_info(
TOKUDB_TRACE(
"name: %s, types: %u %u, nullable: %d, null_offset: %d, is_null_field: "
"%d, is_null %d, pack_length %u",
- curr_field->field_name,
+ curr_field->field_name.str,
curr_field->real_type(),
mysql_to_toku_type(curr_field),
curr_field->null_bit,
@@ -132,7 +132,7 @@ void ha_tokudb::print_alter_info(
TOKUDB_TRACE(
"name: %s, types: %u %u, nullable: %d, null_offset: %d, "
"is_null_field: %d, is_null %d, pack_length %u",
- curr_field->field_name,
+ curr_field->field_name.str,
curr_field->real_type(),
mysql_to_toku_type(curr_field),
curr_field->null_bit,
@@ -398,7 +398,7 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
TOKUDB_TRACE(
"Added column: index %d, name %s",
curr_added_index,
- curr_added_field->field_name);
+ curr_added_field->field_name.str);
}
}
result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
@@ -427,7 +427,7 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
TOKUDB_TRACE(
"Dropped column: index %d, name %s",
curr_dropped_index,
- curr_dropped_field->field_name);
+ curr_dropped_field->field_name.str);
}
}
result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
@@ -1125,7 +1125,7 @@ int ha_tokudb::alter_table_expand_varchar_offsets(
static bool field_in_key(KEY *key, Field *field) {
for (uint i = 0; i < key->user_defined_key_parts; i++) {
KEY_PART_INFO *key_part = &key->key_part[i];
- if (strcmp(key_part->field->field_name, field->field_name) == 0)
+ if (strcmp(key_part->field->field_name.str, field->field_name.str) == 0)
return true;
}
return false;
diff --git a/storage/tokudb/ha_tokudb_alter_common.cc b/storage/tokudb/ha_tokudb_alter_common.cc
index d41a676de1f..17f9a4daa39 100644
--- a/storage/tokudb/ha_tokudb_alter_common.cc
+++ b/storage/tokudb/ha_tokudb_alter_common.cc
@@ -697,8 +697,8 @@ static int find_changed_columns(
sql_print_error(
"Two fields that were supposedly the same are not: %s in "
"original, %s in new",
- curr_field_in_orig->field_name,
- curr_field_in_new->field_name);
+ curr_field_in_orig->field_name.str,
+ curr_field_in_new->field_name.str);
retval = 1;
goto cleanup;
}
diff --git a/storage/tokudb/ha_tokudb_update.cc b/storage/tokudb/ha_tokudb_update.cc
index 23de81f3d8a..a6c72506448 100644
--- a/storage/tokudb/ha_tokudb_update.cc
+++ b/storage/tokudb/ha_tokudb_update.cc
@@ -91,7 +91,7 @@ static void dump_item(Item* item) {
":field=%s.%s.%s",
field_item->db_name,
field_item->table_name,
- field_item->field_name);
+ field_item->field_name.str);
break;
}
case Item::COND_ITEM: {
@@ -141,7 +141,7 @@ static Field* find_field_by_name(TABLE* table, Item* item) {
Field *found_field = NULL;
for (uint i = 0; i < table->s->fields; i++) {
Field *test_field = table->s->field[i];
- if (strcmp(field_item->field_name, test_field->field_name) == 0) {
+ if (strcmp(field_item->field_name.str, test_field->field_name.str) == 0) {
found_field = test_field;
break;
}
@@ -290,7 +290,7 @@ static bool check_insert_value(Item* item, const char* field_name) {
if (value_item->arg->type() != Item::FIELD_ITEM)
return false;
Item_field* arg = static_cast<Item_field*>(value_item->arg);
- if (strcmp(field_name, arg->field_name) != 0)
+ if (strcmp(field_name, arg->field_name.str) != 0)
return false;
return true;
}
@@ -315,7 +315,7 @@ static bool check_x_op_constant(
if (arguments[0]->type() != Item::FIELD_ITEM)
return false;
Item_field* arg0 = static_cast<Item_field*>(arguments[0]);
- if (strcmp(field_name, arg0->field_name) != 0)
+ if (strcmp(field_name, arg0->field_name.str) != 0)
return false;
if (!check_int_result(arguments[1]))
if (!(allow_insert_value &&
@@ -359,11 +359,11 @@ static bool check_decr_floor_expression(Field* lhs_field, Item* item) {
uint n = item_func->argument_count();
if (n != 3)
return false;
- if (!check_x_equal_0(lhs_field->field_name, arguments[0]))
+ if (!check_x_equal_0(lhs_field->field_name.str, arguments[0]))
return false;
if (arguments[1]->type() != Item::INT_ITEM || arguments[1]->val_int() != 0)
return false;
- if (!check_x_minus_1(lhs_field->field_name, arguments[2]))
+ if (!check_x_minus_1(lhs_field->field_name.str, arguments[2]))
return false;
if (!(lhs_field->flags & UNSIGNED_FLAG))
return false;
@@ -394,14 +394,14 @@ static bool check_update_expression(
return true;
Item* item_constant;
if (check_x_op_constant(
- lhs_field->field_name,
+ lhs_field->field_name.str,
rhs_item,
"+",
&item_constant,
allow_insert_value))
return true;
if (check_x_op_constant(
- lhs_field->field_name,
+ lhs_field->field_name.str,
rhs_item,
"-",
&item_constant,
@@ -455,7 +455,7 @@ static bool full_field_in_key(TABLE* table, Field* field) {
KEY* key = &table->s->key_info[table->s->primary_key];
for (uint i = 0; i < key->user_defined_key_parts; i++) {
KEY_PART_INFO* key_part = &key->key_part[i];
- if (strcmp(field->field_name, key_part->field->field_name) == 0) {
+ if (strcmp(field->field_name.str, key_part->field->field_name.str) == 0) {
return key_part->length == field->field_length;
}
}
diff --git a/storage/tokudb/hatoku_cmp.cc b/storage/tokudb/hatoku_cmp.cc
index cb02e4ff13a..ee57e064fbf 100644
--- a/storage/tokudb/hatoku_cmp.cc
+++ b/storage/tokudb/hatoku_cmp.cc
@@ -3031,7 +3031,7 @@ static uint32_t pack_key_from_desc(
}
static bool fields_have_same_name(Field* a, Field* b) {
- return strcmp(a->field_name, b->field_name) == 0;
+ return strcmp(a->field_name.str, b->field_name.str) == 0;
}
static bool fields_are_same_type(Field* a, Field* b) {
diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc
index c3fb6afed73..4fa40c4e45b 100644
--- a/storage/tokudb/hatoku_hton.cc
+++ b/storage/tokudb/hatoku_hton.cc
@@ -101,7 +101,7 @@ static int tokudb_discover3(
THD* thd,
const char* db,
const char* name,
- char* path,
+ const char* path,
uchar** frmblob,
size_t* frmlen);
handlerton* tokudb_hton;
@@ -1207,7 +1207,7 @@ static int tokudb_discover3(
THD* thd,
const char* db,
const char* name,
- char* path,
+ const char* path,
uchar** frmblob,
size_t* frmlen) {
diff --git a/storage/tokudb/mysql-test/tokudb/r/type_float.result b/storage/tokudb/mysql-test/tokudb/r/type_float.result
index 6387cea5384..f8ce24f08c4 100644
--- a/storage/tokudb/mysql-test/tokudb/r/type_float.result
+++ b/storage/tokudb/mysql-test/tokudb/r/type_float.result
@@ -233,12 +233,12 @@ insert into t2 values ("1.23456780");
create table t3 select * from t2 union select * from t1;
select * from t3;
d
-1.2345678
-100000000
+1.234567800
+100000000.000000000
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
- `d` double DEFAULT NULL
+ `d` double(18,9) DEFAULT NULL
) ENGINE=ENGINE DEFAULT CHARSET=latin1
drop table t1, t2, t3;
create table t1 select 105213674794682365.00 + 0.0 x;
diff --git a/storage/tokudb/mysql-test/tokudb/r/type_ranges.result b/storage/tokudb/mysql-test/tokudb/r/type_ranges.result
index 1c9cd769a14..38252e870df 100644
--- a/storage/tokudb/mysql-test/tokudb/r/type_ranges.result
+++ b/storage/tokudb/mysql-test/tokudb/r/type_ranges.result
@@ -273,7 +273,7 @@ drop table t2;
create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(11) unsigned NULL NO PRI NULL #
+auto bigint(11) unsigned NULL NO PRI NULL #
t1 int(1) NULL NO NULL #
t2 varchar(1) latin1_swedish_ci NO NULL #
t3 varchar(256) latin1_swedish_ci NO NULL #
diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc
index f9995302d49..5431cbab7aa 100644
--- a/storage/tokudb/tokudb_dir_cmd.cc
+++ b/storage/tokudb/tokudb_dir_cmd.cc
@@ -42,14 +42,14 @@ static int MDL_and_TDC(THD *thd,
const char *table,
const dir_cmd_callbacks &cb) {
int error;
- LEX_STRING db_arg;
- LEX_STRING table_arg;
+ LEX_CSTRING db_arg;
+ LEX_CSTRING table_arg;
db_arg.str = const_cast<char *>(db);
db_arg.length = strlen(db);;
table_arg.str = const_cast<char *>(table);
table_arg.length = strlen(table);
- Table_ident table_ident(thd, db_arg, table_arg, true);;
+ Table_ident table_ident(thd, &db_arg, &table_arg, true);;
thd->lex->select_lex.add_table_to_list(
thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0);
/* The lock will be released at the end of mysq_execute_command() */
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index b797c0a2114..6097f87b43d 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -3319,7 +3319,7 @@ innobase_query_caching_of_table_permitted(
THD* thd, /*!< in: thd of the user who is trying to
store a result to the query cache or
retrieve it */
- char* full_name, /*!< in: normalized path to the table */
+ const char* full_name, /*!< in: normalized path to the table */
uint full_name_len, /*!< in: length of the normalized path
to the table */
ulonglong *unused) /*!< unused for this engine */
@@ -6142,7 +6142,7 @@ ha_innobase::innobase_initialize_autoinc()
ut_a(prebuilt->trx == thd_to_trx(user_thd));
- col_name = field->field_name;
+ col_name = field->field_name.str;
index = innobase_get_index(table->s->next_number_index);
/* Execute SELECT MAX(col_name) FROM TABLE; */
@@ -8060,7 +8060,7 @@ build_template_field(
"MySQL table %s field %lu name %s",
table->s->table_name.str,
j,
- table->field[j]->field_name);
+ table->field[j]->field_name.str);
}
ib_logf(IB_LOG_LEVEL_ERROR,
@@ -9058,7 +9058,7 @@ calc_row_difference(
if (field_mysql_type == MYSQL_TYPE_LONGLONG
&& prebuilt->table->fts
&& innobase_strcasecmp(
- field->field_name, FTS_DOC_ID_COL_NAME) == 0) {
+ field->field_name.str, FTS_DOC_ID_COL_NAME) == 0) {
doc_id = (doc_id_t) mach_read_from_n_little_endian(
n_ptr, 8);
if (doc_id == 0) {
@@ -9322,7 +9322,7 @@ int
ha_innobase::update_row(
/*====================*/
const uchar* old_row, /*!< in: old row in MySQL format */
- uchar* new_row) /*!< in: new row in MySQL format */
+ const uchar* new_row) /*!< in: new row in MySQL format */
{
upd_t* uvect;
dberr_t error;
@@ -11204,7 +11204,7 @@ create_table_check_doc_id_col(
col_len = field->pack_length();
- if (innobase_strcasecmp(field->field_name,
+ if (innobase_strcasecmp(field->field_name.str,
FTS_DOC_ID_COL_NAME) == 0) {
/* Note the name is case sensitive due to
@@ -11212,7 +11212,7 @@ create_table_check_doc_id_col(
if (col_type == DATA_INT
&& !field->real_maybe_null()
&& col_len == sizeof(doc_id_t)
- && (strcmp(field->field_name,
+ && (strcmp(field->field_name.str,
FTS_DOC_ID_COL_NAME) == 0)) {
*doc_id_col = i;
} else {
@@ -11224,7 +11224,7 @@ create_table_check_doc_id_col(
"of BIGINT NOT NULL type, and named "
"in all capitalized characters");
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
*doc_id_col = ULINT_UNDEFINED;
}
@@ -11370,7 +11370,7 @@ create_table_def(
"column type and try to re-create "
"the table with an appropriate "
"column type.",
- table->name, field->field_name);
+ table->name, field->field_name.str);
goto err_col;
}
@@ -11420,9 +11420,9 @@ create_table_def(
/* First check whether the column to be added has a
system reserved name. */
- if (dict_col_name_is_reserved(field->field_name)){
+ if (dict_col_name_is_reserved(field->field_name.str)){
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
err_col:
dict_mem_table_free(table);
mem_heap_free(heap);
@@ -11433,7 +11433,7 @@ err_col:
}
dict_mem_table_add_col(table, heap,
- field->field_name,
+ field->field_name.str,
col_type,
dtype_form_prtype(
(ulint) field->type()
@@ -11511,7 +11511,7 @@ create_index(
for (ulint i = 0; i < key->user_defined_key_parts; i++) {
KEY_PART_INFO* key_part = key->key_part + i;
dict_mem_index_add_field(
- index, key_part->field->field_name, 0);
+ index, key_part->field->field_name.str, 0);
}
DBUG_RETURN(convert_error_code_to_mysql(
@@ -11562,8 +11562,8 @@ create_index(
field = form->field[j];
if (0 == innobase_strcasecmp(
- field->field_name,
- key_part->field->field_name)) {
+ field->field_name.str,
+ key_part->field->field_name.str)) {
/* Found the corresponding column */
goto found;
@@ -11596,7 +11596,7 @@ found:
"inappropriate data type. Table "
"name %s, column name %s.",
table_name,
- key_part->field->field_name);
+ key_part->field->field_name.str);
prefix_len = 0;
}
@@ -11607,7 +11607,7 @@ found:
field_lengths[i] = key_part->length;
dict_mem_index_add_field(
- index, key_part->field->field_name, prefix_len);
+ index, key_part->field->field_name.str, prefix_len);
}
ut_ad(key->flags & HA_FULLTEXT || !(index->type & DICT_FTS));
@@ -12083,7 +12083,7 @@ innobase_table_flags(
/* Do a pre-check on FTS DOC ID index */
if (!(key->flags & HA_NOSAME)
|| strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
- || strcmp(key->key_part[0].field->field_name,
+ || strcmp(key->key_part[0].field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
fts_doc_id_index_bad = key->name;
}
@@ -16836,7 +16836,7 @@ my_bool
ha_innobase::register_query_cache_table(
/*====================================*/
THD* thd, /*!< in: user thread handle */
- char* table_key, /*!< in: normalized path to the
+ const char* table_key, /*!< in: normalized path to the
table */
uint key_length, /*!< in: length of the normalized
path to the table */
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 426136e4d51..3bb67532954 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -148,7 +148,7 @@ class ha_innobase: public handler
my_bool is_fake_change_enabled(THD *thd);
int write_row(uchar * buf);
- int update_row(const uchar * old_data, uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
bool was_semi_consistent_read();
void try_semi_consistent_read(bool yes);
@@ -235,7 +235,7 @@ class ha_innobase: public handler
/*
ask handler about permission to cache table during query registration
*/
- my_bool register_query_cache_table(THD *thd, char *table_key,
+ my_bool register_query_cache_table(THD *thd, const char *table_key,
uint key_length,
qc_engine_callback *call_back,
ulonglong *engine_data);
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 957e23d608a..0e7cc9a655b 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -452,7 +452,7 @@ ha_innobase::check_if_supported_inplace_alter(
is TIMESTAMP and it is defined as NOT NULL and
it has either constant default or function default
we must use "Copy" method. */
- if (is_timestamp_type(def->sql_type)) {
+ if (def->is_timestamp_type()) {
if ((def->flags & NOT_NULL_FLAG) != 0 && // NOT NULL
(def->default_value != NULL || // constant default ?
def->unireg_check != Field::NONE)) { // function default
@@ -533,7 +533,7 @@ ha_innobase::check_if_supported_inplace_alter(
&& innobase_fulltext_exist(altered_table)
&& !my_strcasecmp(
system_charset_info,
- key_part->field->field_name,
+ key_part->field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS);
@@ -590,7 +590,7 @@ ha_innobase::check_if_supported_inplace_alter(
if (!my_strcasecmp(
system_charset_info,
- (*fp)->field_name,
+ (*fp)->field_name.str,
FTS_DOC_ID_COL_NAME)) {
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS);
@@ -859,7 +859,7 @@ no_match:
}
if (innobase_strcasecmp(col_names[j],
- key_part.field->field_name)) {
+ key_part.field->field_name.str)) {
/* Name mismatch */
goto no_match;
}
@@ -1515,7 +1515,7 @@ name_ok:
}
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
return(ER_WRONG_KEY_COLUMN);
}
@@ -1531,7 +1531,7 @@ name_ok:
}
my_error(ER_WRONG_KEY_COLUMN, MYF(0), "InnoDB",
- field->field_name);
+ field->field_name.str);
return(ER_WRONG_KEY_COLUMN);
}
}
@@ -1570,7 +1570,7 @@ innobase_create_index_field_def(
ut_a(field);
index_field->col_no = key_part->fieldnr;
- index_field->col_name = altered_table ? field->field_name : fields[key_part->fieldnr]->field_name;
+ index_field->col_name = altered_table ? field->field_name.str : fields[key_part->fieldnr]->field_name.str;
col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
@@ -1695,19 +1695,19 @@ innobase_fts_check_doc_id_col(
stored_in_db()))
sql_idx++;
if (my_strcasecmp(system_charset_info,
- field->field_name, FTS_DOC_ID_COL_NAME)) {
+ field->field_name.str, FTS_DOC_ID_COL_NAME)) {
continue;
}
- if (strcmp(field->field_name, FTS_DOC_ID_COL_NAME)) {
+ if (strcmp(field->field_name.str, FTS_DOC_ID_COL_NAME)) {
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
} else if (field->type() != MYSQL_TYPE_LONGLONG
|| field->pack_length() != 8
|| field->real_maybe_null()
|| !(field->flags & UNSIGNED_FLAG)) {
my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0),
- field->field_name);
+ field->field_name.str);
} else {
*fts_doc_col_no = i;
}
@@ -1778,7 +1778,7 @@ innobase_fts_check_doc_id_index(
if ((key.flags & HA_NOSAME)
&& key.user_defined_key_parts == 1
&& !strcmp(key.name, FTS_DOC_ID_INDEX_NAME)
- && !strcmp(key.key_part[0].field->field_name,
+ && !strcmp(key.key_part[0].field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
if (fts_doc_col_no) {
*fts_doc_col_no = ULINT_UNDEFINED;
@@ -1857,7 +1857,7 @@ innobase_fts_check_doc_id_index_in_def(
if (!(key->flags & HA_NOSAME)
|| key->user_defined_key_parts != 1
|| strcmp(key->name, FTS_DOC_ID_INDEX_NAME)
- || strcmp(key->key_part[0].field->field_name,
+ || strcmp(key->key_part[0].field->field_name.str,
FTS_DOC_ID_COL_NAME)) {
return(FTS_INCORRECT_DOC_ID_INDEX);
}
@@ -2464,7 +2464,7 @@ innobase_check_foreigns(
if (!new_field || (new_field->flags & NOT_NULL_FLAG)) {
if (innobase_check_foreigns_low(
user_table, drop_fk, n_drop_fk,
- (*fp)->field_name, !new_field)) {
+ (*fp)->field_name.str, !new_field)) {
return(true);
}
}
@@ -2693,7 +2693,7 @@ innobase_get_col_names(
for (uint old_i = 0; table->field[old_i]; old_i++) {
if (new_field->field == table->field[old_i]) {
- cols[old_i] = new_field->field_name;
+ cols[old_i] = new_field->field_name.str;
break;
}
}
@@ -2980,7 +2980,7 @@ prepare_inplace_alter_table_dict(
dict_mem_table_free(
ctx->new_table);
my_error(ER_WRONG_KEY_COLUMN, MYF(0),
- field->field_name);
+ field->field_name.str);
goto new_clustered_failed;
}
} else {
@@ -3007,16 +3007,16 @@ prepare_inplace_alter_table_dict(
}
}
- if (dict_col_name_is_reserved(field->field_name)) {
+ if (dict_col_name_is_reserved(field->field_name.str)) {
dict_mem_table_free(ctx->new_table);
my_error(ER_WRONG_COLUMN_NAME, MYF(0),
- field->field_name);
+ field->field_name.str);
goto new_clustered_failed;
}
dict_mem_table_add_col(
ctx->new_table, ctx->heap,
- field->field_name,
+ field->field_name.str,
col_type,
dtype_form_prtype(field_type, charset_no),
col_len);
@@ -3656,7 +3656,7 @@ err_exit_no_heap:
cf_it.rewind();
while (Create_field* cf = cf_it++) {
if (cf->field == *fp) {
- name = cf->field_name;
+ name = cf->field_name.str;
goto check_if_ok_to_rename;
}
}
@@ -3666,7 +3666,7 @@ check_if_ok_to_rename:
/* Prohibit renaming a column from FTS_DOC_ID
if full-text indexes exist. */
if (!my_strcasecmp(system_charset_info,
- (*fp)->field_name,
+ (*fp)->field_name.str,
FTS_DOC_ID_COL_NAME)
&& innobase_fulltext_exist(altered_table)) {
my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN,
@@ -4843,8 +4843,8 @@ innobase_rename_columns_try(
if (cf->field == *fp) {
if (innobase_rename_column_try(
ctx->old_table, trx, table_name, i,
- cf->field->field_name,
- cf->field_name,
+ cf->field->field_name.str,
+ cf->field_name.str,
ctx->need_rebuild())) {
return(true);
}
@@ -4891,8 +4891,8 @@ innobase_rename_columns_cache(
while (Create_field* cf = cf_it++) {
if (cf->field == *fp) {
dict_mem_table_col_rename(user_table, i,
- cf->field->field_name,
- cf->field_name);
+ cf->field->field_name.str,
+ cf->field_name.str);
goto processed_field;
}
}
@@ -4954,7 +4954,7 @@ commit_get_autoinc(
dict_table_autoinc_lock(ctx->old_table);
err = row_search_max_autoinc(
- index, autoinc_field->field_name, &max_value_table);
+ index, autoinc_field->field_name.str, &max_value_table);
if (err != DB_SUCCESS) {
ut_ad(0);
diff --git a/support-files/build-tags b/support-files/build-tags
index e94b7bed298..660a7d7f9fc 100755
--- a/support-files/build-tags
+++ b/support-files/build-tags
@@ -5,8 +5,8 @@ rm -f TAGS
if git rev-parse HEAD >/dev/null 2>&1
then
cd `git rev-parse --show-toplevel`
- echo client storage dbug libmysql sql-common \
- sql extra mysys mysys_ssl strings regex pcre vio include \
+ echo sql mysys strings client storage dbug libmysql sql-common \
+ extra mysys_ssl strings regex pcre vio include \
tools unittest plugin libmysqld | \
xargs -n1 git ls-files | grep -v '\.jar$' | grep -v '\.xz$' | \
xargs etags -o TAGS --append
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 383036ff092..734f7790025 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -8399,6 +8399,76 @@ static void test_list_fields()
}
+static void test_list_fields_default()
+{
+ int rc, i;
+ myheader("test_list_fields_default");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "CREATE TABLE t1 ("
+ " i1 INT NOT NULL DEFAULT 0,"
+ " i3 BIGINT UNSIGNED NOT NULL DEFAULT 0xFFFFFFFFFFFFFFFF,"
+ " s1 VARCHAR(10) CHARACTER SET latin1 NOT NULL DEFAULT 's1def',"
+ " d1 DECIMAL(31,1) NOT NULL DEFAULT 111111111122222222223333333333.9,"
+ " t1 DATETIME(6) NOT NULL DEFAULT '2001-01-01 10:20:30.123456',"
+ " e1 ENUM('a','b') NOT NULL DEFAULT 'a'"
+ ")");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1");
+ myquery(rc);
+
+ /*
+ Checking that mysql_list_fields() returns the same result
+ for a TABLE and a VIEW on the same table.
+ */
+ for (i= 0; i < 2; i++)
+ {
+ const char *table_name= i == 0 ? "t1" : "v1";
+ MYSQL_RES *result= mysql_list_fields(mysql, table_name, NULL);
+ mytest(result);
+
+ rc= my_process_result_set(result);
+ DIE_UNLESS(rc == 0);
+
+ verify_prepare_field(result, 0, "i1", "i1", MYSQL_TYPE_LONG,
+ table_name, table_name, current_db,
+ 11, "0");
+
+ verify_prepare_field(result, 1, "i3", "i3", MYSQL_TYPE_LONGLONG,
+ table_name, table_name, current_db,
+ 20, "18446744073709551615");
+
+ verify_prepare_field(result, 2, "s1", "s1", MYSQL_TYPE_VAR_STRING,
+ table_name, table_name, current_db,
+ 10, "s1def");
+
+ verify_prepare_field(result, 3, "d1", "d1", MYSQL_TYPE_NEWDECIMAL,
+ table_name, table_name, current_db,
+ 33, "111111111122222222223333333333.9");
+
+ verify_prepare_field(result, 4, "t1", "t1", MYSQL_TYPE_DATETIME,
+ table_name, table_name, current_db,
+ 26, "2001-01-01 10:20:30.123456");
+
+ verify_prepare_field(result, 5, "e1", "e1", MYSQL_TYPE_STRING,
+ table_name, table_name, current_db,
+ 1, "a");
+
+ mysql_free_result(result);
+ }
+
+ myquery(mysql_query(mysql, "DROP VIEW v1"));
+ myquery(mysql_query(mysql, "DROP TABLE t1"));
+}
+
+
static void test_bug19671()
{
MYSQL_RES *result;
@@ -19663,6 +19733,7 @@ static struct my_tests_st my_tests[]= {
{ "test_fetch_column", test_fetch_column },
{ "test_mem_overun", test_mem_overun },
{ "test_list_fields", test_list_fields },
+ { "test_list_fields_default", test_list_fields_default },
{ "test_free_result", test_free_result },
{ "test_free_store_result", test_free_store_result },
{ "test_sqlmode", test_sqlmode },